Add --trace_folder to aapt2
Add a tracing API and instrument key functions in order to profile aapt2 bottleneck. The API allows to generate systrace fragment files. Impact on performance is neglibible with each Trace requiring less than 1us and the final Flush operation at the end of a command requiring around 40us. Bug: None Test: None Change-Id: I51b564d3694e9384679f43b878b32295527dddf6
This commit is contained in:
@@ -141,6 +141,7 @@ cc_library_host_static {
|
||||
"ResourceValues.cpp",
|
||||
"SdkConstants.cpp",
|
||||
"StringPool.cpp",
|
||||
"trace/TraceBuffer.cpp",
|
||||
"xml/XmlActionExecutor.cpp",
|
||||
"xml/XmlDom.cpp",
|
||||
"xml/XmlPullParser.cpp",
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "cmd/Link.h"
|
||||
#include "cmd/Optimize.h"
|
||||
#include "io/FileStream.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Files.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -107,9 +108,12 @@ class DaemonCommand : public Command {
|
||||
: Command("daemon", "m"), out_(out), diagnostics_(diagnostics) {
|
||||
SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n"
|
||||
"command. The end of an invocation is signaled by providing an empty line.");
|
||||
AddOptionalFlag("--trace_folder", "Generate systrace json trace fragment to specified folder.",
|
||||
&trace_folder_);
|
||||
}
|
||||
|
||||
int Action(const std::vector<std::string>& /* args */) override {
|
||||
int Action(const std::vector<std::string>& arguments) override {
|
||||
TRACE_FLUSH_ARGS(trace_folder_ ? trace_folder_.value() : "", "daemon", arguments);
|
||||
text::Printer printer(out_);
|
||||
std::cout << "Ready" << std::endl;
|
||||
|
||||
@@ -150,6 +154,7 @@ class DaemonCommand : public Command {
|
||||
private:
|
||||
io::FileOutputStream* out_;
|
||||
IDiagnostics* diagnostics_;
|
||||
Maybe<std::string> trace_folder_;
|
||||
};
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "NameMangler.h"
|
||||
#include "ResourceValues.h"
|
||||
#include "ValueVisitor.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "text/Unicode.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -79,6 +80,7 @@ ResourceTablePackage* ResourceTable::FindPackageById(uint8_t id) const {
|
||||
}
|
||||
|
||||
ResourceTablePackage* ResourceTable::CreatePackage(const StringPiece& name, Maybe<uint8_t> id) {
|
||||
TRACE_CALL();
|
||||
ResourceTablePackage* package = FindOrCreatePackage(name);
|
||||
if (id && !package->id) {
|
||||
package->id = id;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "android-base/utf8.h"
|
||||
#include "androidfw/StringPiece.h"
|
||||
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using android::base::StringPrintf;
|
||||
@@ -178,6 +179,7 @@ void Command::Usage(std::ostream* out) {
|
||||
}
|
||||
|
||||
int Command::Execute(const std::vector<StringPiece>& args, std::ostream* out_error) {
|
||||
TRACE_NAME_ARGS("Command::Execute", args);
|
||||
std::vector<std::string> file_args;
|
||||
|
||||
for (size_t i = 0; i < args.size(); i++) {
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "io/StringStream.h"
|
||||
#include "io/Util.h"
|
||||
#include "io/ZipArchive.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Files.h"
|
||||
#include "util/Maybe.h"
|
||||
#include "util/Util.h"
|
||||
@@ -141,6 +142,7 @@ static std::string BuildIntermediateContainerFilename(const ResourcePathData& da
|
||||
static bool CompileTable(IAaptContext* context, const CompileOptions& options,
|
||||
const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
|
||||
const std::string& output_path) {
|
||||
TRACE_CALL();
|
||||
ResourceTable table;
|
||||
{
|
||||
auto fin = file->OpenInputStream();
|
||||
@@ -286,6 +288,7 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options,
|
||||
static bool WriteHeaderAndDataToWriter(const StringPiece& output_path, const ResourceFile& file,
|
||||
io::KnownSizeInputStream* in, IArchiveWriter* writer,
|
||||
IDiagnostics* diag) {
|
||||
TRACE_CALL();
|
||||
// Start the entry so we can write the header.
|
||||
if (!writer->StartEntry(output_path, 0)) {
|
||||
diag->Error(DiagMessage(output_path) << "failed to open file");
|
||||
@@ -352,6 +355,7 @@ static bool IsValidFile(IAaptContext* context, const std::string& input_path) {
|
||||
static bool CompileXml(IAaptContext* context, const CompileOptions& options,
|
||||
const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
|
||||
const std::string& output_path) {
|
||||
TRACE_CALL();
|
||||
if (context->IsVerbose()) {
|
||||
context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling XML");
|
||||
}
|
||||
@@ -451,6 +455,7 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options,
|
||||
static bool CompilePng(IAaptContext* context, const CompileOptions& options,
|
||||
const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
|
||||
const std::string& output_path) {
|
||||
TRACE_CALL();
|
||||
if (context->IsVerbose()) {
|
||||
context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling PNG");
|
||||
}
|
||||
@@ -558,6 +563,7 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options,
|
||||
static bool CompileFile(IAaptContext* context, const CompileOptions& options,
|
||||
const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
|
||||
const std::string& output_path) {
|
||||
TRACE_CALL();
|
||||
if (context->IsVerbose()) {
|
||||
context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling file");
|
||||
}
|
||||
@@ -632,6 +638,7 @@ class CompileContext : public IAaptContext {
|
||||
|
||||
int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
|
||||
CompileOptions& options) {
|
||||
TRACE_CALL();
|
||||
bool error = false;
|
||||
|
||||
// Iterate over the input files in a stable, platform-independent manner
|
||||
@@ -707,6 +714,7 @@ int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter*
|
||||
}
|
||||
|
||||
int CompileCommand::Action(const std::vector<std::string>& args) {
|
||||
TRACE_FLUSH(trace_folder_? trace_folder_.value() : "", "CompileCommand::Action");
|
||||
CompileContext context(diagnostic_);
|
||||
context.SetVerbose(options_.verbose);
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ class CompileCommand : public Command {
|
||||
"Sets the visibility of the compiled resources to the specified\n"
|
||||
"level. Accepted levels: public, private, default", &visibility_);
|
||||
AddOptionalSwitch("-v", "Enables verbose logging", &options_.verbose);
|
||||
AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.",
|
||||
&trace_folder_);
|
||||
}
|
||||
|
||||
int Action(const std::vector<std::string>& args) override;
|
||||
@@ -68,6 +70,7 @@ class CompileCommand : public Command {
|
||||
IDiagnostics* diagnostic_;
|
||||
CompileOptions options_;
|
||||
Maybe<std::string> visibility_;
|
||||
Maybe<std::string> trace_folder_;
|
||||
};
|
||||
|
||||
int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "process/IResourceTableConsumer.h"
|
||||
#include "process/SymbolTable.h"
|
||||
#include "split/TableSplitter.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Files.h"
|
||||
#include "xml/XmlDom.h"
|
||||
|
||||
@@ -213,6 +214,7 @@ class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
|
||||
static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res,
|
||||
const StringPiece& path, bool keep_raw_values, bool utf16,
|
||||
OutputFormat format, IArchiveWriter* writer) {
|
||||
TRACE_CALL();
|
||||
if (context->IsVerbose()) {
|
||||
context->GetDiagnostics()->Note(DiagMessage(path) << "writing to archive (keep_raw_values="
|
||||
<< (keep_raw_values ? "true" : "false")
|
||||
@@ -250,6 +252,7 @@ static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res,
|
||||
|
||||
// Inflates an XML file from the source path.
|
||||
static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
|
||||
TRACE_CALL();
|
||||
FileInputStream fin(path);
|
||||
if (fin.HadError()) {
|
||||
diag->Error(DiagMessage(path) << "failed to load XML file: " << fin.GetError());
|
||||
@@ -421,6 +424,7 @@ std::vector<T> make_singleton_vec(T&& val) {
|
||||
|
||||
std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVersionXmlFile(
|
||||
ResourceTable* table, FileOperation* file_op) {
|
||||
TRACE_CALL();
|
||||
xml::XmlResource* doc = file_op->xml_to_flatten.get();
|
||||
const Source& src = doc->file.source;
|
||||
|
||||
@@ -489,6 +493,7 @@ static auto kDrawableVersions = std::map<std::string, ApiVersion>{
|
||||
};
|
||||
|
||||
bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
|
||||
TRACE_CALL();
|
||||
bool error = false;
|
||||
std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
|
||||
|
||||
@@ -806,6 +811,7 @@ class Linker {
|
||||
// Creates a SymbolTable that loads symbols from the various APKs.
|
||||
// Pre-condition: context_->GetCompilationPackage() needs to be set.
|
||||
bool LoadSymbolsFromIncludePaths() {
|
||||
TRACE_NAME("LoadSymbolsFromIncludePaths: #" + std::to_string(options_.include_paths.size()));
|
||||
auto asset_source = util::make_unique<AssetManagerSymbolSource>();
|
||||
for (const std::string& path : options_.include_paths) {
|
||||
if (context_->IsVerbose()) {
|
||||
@@ -891,6 +897,7 @@ class Linker {
|
||||
}
|
||||
|
||||
Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
|
||||
TRACE_CALL();
|
||||
// Make sure the first element is <manifest> with package attribute.
|
||||
xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
|
||||
if (manifest_el == nullptr) {
|
||||
@@ -1041,6 +1048,7 @@ class Linker {
|
||||
}
|
||||
|
||||
bool FlattenTable(ResourceTable* table, OutputFormat format, IArchiveWriter* writer) {
|
||||
TRACE_CALL();
|
||||
switch (format) {
|
||||
case OutputFormat::kApk: {
|
||||
BigBuffer buffer(1024);
|
||||
@@ -1114,6 +1122,7 @@ class Linker {
|
||||
}
|
||||
|
||||
bool GenerateJavaClasses() {
|
||||
TRACE_CALL();
|
||||
// The set of packages whose R class to call in the main classes onResourcesLoaded callback.
|
||||
std::vector<std::string> packages_to_callback;
|
||||
|
||||
@@ -1197,6 +1206,7 @@ class Linker {
|
||||
}
|
||||
|
||||
bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
|
||||
TRACE_CALL();
|
||||
if (!options_.generate_java_class_path) {
|
||||
return true;
|
||||
}
|
||||
@@ -1254,6 +1264,7 @@ class Linker {
|
||||
}
|
||||
|
||||
bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) {
|
||||
TRACE_CALL();
|
||||
if (!out) {
|
||||
return true;
|
||||
}
|
||||
@@ -1278,6 +1289,7 @@ class Linker {
|
||||
}
|
||||
|
||||
bool MergeStaticLibrary(const std::string& input, bool override) {
|
||||
TRACE_CALL();
|
||||
if (context_->IsVerbose()) {
|
||||
context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input);
|
||||
}
|
||||
@@ -1328,6 +1340,7 @@ class Linker {
|
||||
|
||||
bool MergeExportedSymbols(const Source& source,
|
||||
const std::vector<SourcedResourceName>& exported_symbols) {
|
||||
TRACE_CALL();
|
||||
// Add the exports of this file to the table.
|
||||
for (const SourcedResourceName& exported_symbol : exported_symbols) {
|
||||
ResourceName res_name = exported_symbol.name;
|
||||
@@ -1353,6 +1366,7 @@ class Linker {
|
||||
}
|
||||
|
||||
bool MergeCompiledFile(const ResourceFile& compiled_file, io::IFile* file, bool override) {
|
||||
TRACE_CALL();
|
||||
if (context_->IsVerbose()) {
|
||||
context_->GetDiagnostics()->Note(DiagMessage()
|
||||
<< "merging '" << compiled_file.name
|
||||
@@ -1371,6 +1385,7 @@ class Linker {
|
||||
// An io::IFileCollection is created from the ZIP file and added to the set of
|
||||
// io::IFileCollections that are open.
|
||||
bool MergeArchive(const std::string& input, bool override) {
|
||||
TRACE_CALL();
|
||||
if (context_->IsVerbose()) {
|
||||
context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input);
|
||||
}
|
||||
@@ -1418,6 +1433,7 @@ class Linker {
|
||||
// All other file types are ignored. This is because these files could be coming from a zip,
|
||||
// where we could have other files like classes.dex.
|
||||
bool MergeFile(io::IFile* file, bool override) {
|
||||
TRACE_CALL();
|
||||
const Source& src = file->GetSource();
|
||||
|
||||
if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) {
|
||||
@@ -1458,6 +1474,7 @@ class Linker {
|
||||
|
||||
while ((entry = reader.Next()) != nullptr) {
|
||||
if (entry->Type() == ContainerEntryType::kResTable) {
|
||||
TRACE_NAME(std::string("Process ResTable:") + file->GetSource().path);
|
||||
pb::ResourceTable pb_table;
|
||||
if (!entry->GetResTable(&pb_table)) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read resource table: "
|
||||
@@ -1478,6 +1495,7 @@ class Linker {
|
||||
return false;
|
||||
}
|
||||
} else if (entry->Type() == ContainerEntryType::kResFile) {
|
||||
TRACE_NAME(std::string("Process ResFile") + file->GetSource().path);
|
||||
pb::internal::CompiledFile pb_compiled_file;
|
||||
off64_t offset;
|
||||
size_t len;
|
||||
@@ -1551,6 +1569,7 @@ class Linker {
|
||||
// to the IArchiveWriter.
|
||||
bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
|
||||
ResourceTable* table) {
|
||||
TRACE_CALL();
|
||||
const bool keep_raw_values = (context_->GetPackageType() == PackageType::kStaticLib)
|
||||
|| options_.keep_raw_values;
|
||||
bool result = FlattenXml(context_, *manifest, kAndroidManifestPath, keep_raw_values,
|
||||
@@ -1632,6 +1651,7 @@ class Linker {
|
||||
}
|
||||
|
||||
int Run(const std::vector<std::string>& input_files) {
|
||||
TRACE_CALL();
|
||||
// Load the AndroidManifest.xml
|
||||
std::unique_ptr<xml::XmlResource> manifest_xml =
|
||||
LoadXml(options_.manifest_path, context_->GetDiagnostics());
|
||||
@@ -1839,6 +1859,7 @@ class Linker {
|
||||
std::vector<ConfigDescription> excluded_configs;
|
||||
|
||||
for (auto& config_string : options_.exclude_configs_) {
|
||||
TRACE_NAME("ConfigDescription::Parse");
|
||||
ConfigDescription config_description;
|
||||
|
||||
if (!ConfigDescription::Parse(config_string, &config_description)) {
|
||||
@@ -2038,6 +2059,7 @@ class Linker {
|
||||
};
|
||||
|
||||
int LinkCommand::Action(const std::vector<std::string>& args) {
|
||||
TRACE_FLUSH(trace_folder_ ? trace_folder_.value() : "", "LinkCommand::Action");
|
||||
LinkContext context(diag_);
|
||||
|
||||
// Expand all argument-files passed into the command line. These start with '@'.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "split/TableSplitter.h"
|
||||
#include "format/binary/TableFlattener.h"
|
||||
#include "link/ManifestFixer.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
namespace aapt {
|
||||
|
||||
@@ -277,6 +278,8 @@ class LinkCommand : public Command {
|
||||
"Do not allow overlays with different visibility levels.",
|
||||
&options_.strict_visibility);
|
||||
AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
|
||||
AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.",
|
||||
&trace_folder_);
|
||||
}
|
||||
|
||||
int Action(const std::vector<std::string>& args) override;
|
||||
@@ -300,6 +303,7 @@ class LinkCommand : public Command {
|
||||
bool proto_format_ = false;
|
||||
Maybe<std::string> stable_id_file_path_;
|
||||
std::vector<std::string> split_args_;
|
||||
Maybe<std::string> trace_folder_;
|
||||
};
|
||||
|
||||
}// namespace aapt
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "androidfw/ResourceTypes.h"
|
||||
|
||||
#include "Source.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/BigBuffer.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -1233,6 +1234,7 @@ getout:
|
||||
|
||||
bool Png::process(const Source& source, std::istream* input,
|
||||
BigBuffer* outBuffer, const PngOptions& options) {
|
||||
TRACE_CALL();
|
||||
png_byte signature[kPngSignatureSize];
|
||||
|
||||
// Read the PNG signature first.
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "android-base/logging.h"
|
||||
#include "android-base/macros.h"
|
||||
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
namespace aapt {
|
||||
|
||||
// Custom deleter that destroys libpng read and info structs.
|
||||
@@ -142,6 +144,7 @@ static void WriteDataToStream(png_structp png_ptr, png_bytep buffer, png_size_t
|
||||
}
|
||||
|
||||
std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in) {
|
||||
TRACE_CALL();
|
||||
// Create a diagnostics that has the source information encoded.
|
||||
SourcePathDiagnostics source_diag(source, context->GetDiagnostics());
|
||||
|
||||
@@ -480,6 +483,7 @@ static void WriteNinePatch(png_structp write_ptr, png_infop write_info_ptr,
|
||||
bool WritePng(IAaptContext* context, const Image* image,
|
||||
const NinePatch* nine_patch, io::OutputStream* out,
|
||||
const PngOptions& options) {
|
||||
TRACE_CALL();
|
||||
// Create and initialize the write png_struct with the default error and
|
||||
// warning handlers.
|
||||
// The header version is also passed in to ensure that this was built against the same
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "ResourceUtils.h"
|
||||
#include "ResourceValues.h"
|
||||
#include "text/Unicode.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "xml/XmlDom.h"
|
||||
|
||||
namespace aapt {
|
||||
@@ -72,6 +73,7 @@ struct IdCollector : public xml::Visitor {
|
||||
} // namespace
|
||||
|
||||
bool XmlIdCollector::Consume(IAaptContext* context, xml::XmlResource* xmlRes) {
|
||||
TRACE_CALL();
|
||||
xmlRes->file.exported_symbols.clear();
|
||||
SourcePathDiagnostics source_diag(xmlRes->file.source, context->GetDiagnostics());
|
||||
IdCollector collector(&xmlRes->file.exported_symbols, &source_diag);
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "android-base/scopeguard.h"
|
||||
#include "android-base/stringprintf.h"
|
||||
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
using ::android::base::StringPrintf;
|
||||
using ::google::protobuf::io::CodedInputStream;
|
||||
using ::google::protobuf::io::CodedOutputStream;
|
||||
@@ -171,6 +173,7 @@ ContainerEntryType ContainerReaderEntry::Type() const {
|
||||
}
|
||||
|
||||
bool ContainerReaderEntry::GetResTable(pb::ResourceTable* out_table) {
|
||||
TRACE_CALL();
|
||||
CHECK(type_ == ContainerEntryType::kResTable) << "reading a kResTable when the type is kResFile";
|
||||
if (length_ > std::numeric_limits<int>::max()) {
|
||||
reader_->error_ = StringPrintf("entry length %zu is too large", length_);
|
||||
@@ -261,6 +264,7 @@ ContainerReader::ContainerReader(io::InputStream* in)
|
||||
total_entry_count_(0u),
|
||||
current_entry_count_(0u),
|
||||
entry_(this) {
|
||||
TRACE_CALL();
|
||||
::google::protobuf::uint32 magic;
|
||||
if (!coded_in_.ReadLittleEndian32(&magic)) {
|
||||
std::ostringstream error;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ValueVisitor.h"
|
||||
#include "format/binary/ChunkWriter.h"
|
||||
#include "format/binary/ResourceTypeExtensions.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/BigBuffer.h"
|
||||
|
||||
using namespace android;
|
||||
@@ -238,6 +239,7 @@ class PackageFlattener {
|
||||
}
|
||||
|
||||
bool FlattenPackage(BigBuffer* buffer) {
|
||||
TRACE_CALL();
|
||||
ChunkWriter pkg_writer(buffer);
|
||||
ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE);
|
||||
pkg_header->id = util::HostToDevice32(package_->id.value());
|
||||
@@ -710,6 +712,7 @@ class PackageFlattener {
|
||||
} // namespace
|
||||
|
||||
bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_CALL();
|
||||
// We must do this before writing the resources, since the string pool IDs may change.
|
||||
table->string_pool.Prune();
|
||||
table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
|
||||
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
using ::android::StringPiece;
|
||||
using ::google::protobuf::io::ZeroCopyOutputStream;
|
||||
|
||||
@@ -26,6 +28,7 @@ namespace io {
|
||||
|
||||
bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path,
|
||||
uint32_t compression_flags, IArchiveWriter* writer) {
|
||||
TRACE_CALL();
|
||||
if (context->IsVerbose()) {
|
||||
context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
|
||||
}
|
||||
@@ -40,6 +43,7 @@ bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std:
|
||||
|
||||
bool CopyFileToArchive(IAaptContext* context, io::IFile* file, const std::string& out_path,
|
||||
uint32_t compression_flags, IArchiveWriter* writer) {
|
||||
TRACE_CALL();
|
||||
std::unique_ptr<io::IData> data = file->OpenAsData();
|
||||
if (!data) {
|
||||
context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
|
||||
@@ -57,6 +61,7 @@ bool CopyFileToArchivePreserveCompression(IAaptContext* context, io::IFile* file
|
||||
bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
|
||||
const std::string& out_path, uint32_t compression_flags,
|
||||
IArchiveWriter* writer) {
|
||||
TRACE_CALL();
|
||||
if (context->IsVerbose()) {
|
||||
context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
|
||||
}
|
||||
@@ -83,6 +88,7 @@ bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite*
|
||||
}
|
||||
|
||||
bool Copy(OutputStream* out, InputStream* in) {
|
||||
TRACE_CALL();
|
||||
const void* in_buffer;
|
||||
size_t in_len;
|
||||
while (in->Next(&in_buffer, &in_len)) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "ziparchive/zip_archive.h"
|
||||
|
||||
#include "Source.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Files.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -93,6 +94,7 @@ ZipFileCollection::ZipFileCollection() : handle_(nullptr) {}
|
||||
|
||||
std::unique_ptr<ZipFileCollection> ZipFileCollection::Create(
|
||||
const StringPiece& path, std::string* out_error) {
|
||||
TRACE_CALL();
|
||||
constexpr static const int32_t kEmptyArchive = -6;
|
||||
|
||||
std::unique_ptr<ZipFileCollection> collection =
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "ResourceTable.h"
|
||||
#include "SdkConstants.h"
|
||||
#include "ValueVisitor.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
using android::ConfigDescription;
|
||||
|
||||
@@ -70,6 +71,7 @@ ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
|
||||
}
|
||||
|
||||
bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_NAME("AutoVersioner::Consume");
|
||||
for (auto& package : table->packages) {
|
||||
for (auto& type : package->types) {
|
||||
if (type->type != ResourceType::kStyle) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "android-base/logging.h"
|
||||
|
||||
#include "ResourceUtils.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Util.h"
|
||||
#include "xml/XmlActionExecutor.h"
|
||||
#include "xml/XmlDom.h"
|
||||
@@ -451,6 +452,7 @@ static bool RenameManifestPackage(const StringPiece& package_override, xml::Elem
|
||||
}
|
||||
|
||||
bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
|
||||
TRACE_CALL();
|
||||
xml::Element* root = xml::FindRootElement(doc->root.get());
|
||||
if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
|
||||
context->GetDiagnostics()->Error(DiagMessage(doc->file.source)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "link/Linkers.h"
|
||||
|
||||
#include "ResourceTable.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
namespace aapt {
|
||||
|
||||
@@ -81,6 +82,7 @@ ProductFilter::ResourceConfigValueIter ProductFilter::SelectProductToKeep(
|
||||
}
|
||||
|
||||
bool ProductFilter::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_NAME("ProductFilter::Consume");
|
||||
bool error = false;
|
||||
for (auto& pkg : table->packages) {
|
||||
for (auto& type : pkg->types) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "link/Linkers.h"
|
||||
#include "process/IResourceTableConsumer.h"
|
||||
#include "process/SymbolTable.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Util.h"
|
||||
#include "xml/XmlUtil.h"
|
||||
|
||||
@@ -353,6 +354,7 @@ bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* referen
|
||||
}
|
||||
|
||||
bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_NAME("ReferenceLinker::Consume");
|
||||
EmptyDeclStack decl_stack;
|
||||
bool error = false;
|
||||
for (auto& package : table->packages) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "DominatorTree.h"
|
||||
#include "ResourceTable.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
using android::ConfigDescription;
|
||||
|
||||
@@ -65,6 +66,7 @@ void RemoveIfExcluded(std::set<std::pair<ConfigDescription, int>>& excluded_conf
|
||||
} // namespace
|
||||
|
||||
bool ResourceExcluder::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_NAME("ResourceExcluder::Consume");
|
||||
for (auto& package : table->packages) {
|
||||
for (auto& type : package->types) {
|
||||
for (auto& entry : type->entries) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ResourceTable.h"
|
||||
#include "ResourceUtils.h"
|
||||
#include "ResourceValues.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "ValueVisitor.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -38,6 +39,7 @@ TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table,
|
||||
}
|
||||
|
||||
bool TableMerger::Merge(const Source& src, ResourceTable* table, bool overlay) {
|
||||
TRACE_CALL();
|
||||
// We allow adding new resources if this is not an overlay, or if the options allow overlays
|
||||
// to add new resources.
|
||||
return MergeImpl(src, table, overlay, options_.auto_add_overlay || !overlay /*allow_new*/);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "link/ReferenceLinker.h"
|
||||
#include "process/IResourceTableConsumer.h"
|
||||
#include "process/SymbolTable.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Util.h"
|
||||
#include "xml/XmlDom.h"
|
||||
|
||||
@@ -151,6 +152,7 @@ class XmlVisitor : public xml::PackageAwareVisitor {
|
||||
} // namespace
|
||||
|
||||
bool XmlReferenceLinker::Consume(IAaptContext* context, xml::XmlResource* resource) {
|
||||
TRACE_NAME("XmlReferenceLinker::Consume");
|
||||
CallSite callsite{resource->file.name.package};
|
||||
|
||||
std::string out_name = resource->file.name.entry;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "DominatorTree.h"
|
||||
#include "ResourceTable.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
using android::ConfigDescription;
|
||||
|
||||
@@ -110,6 +111,7 @@ static void DedupeEntry(IAaptContext* context, ResourceEntry* entry) {
|
||||
} // namespace
|
||||
|
||||
bool ResourceDeduper::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_CALL();
|
||||
for (auto& package : table->packages) {
|
||||
for (auto& type : package->types) {
|
||||
for (auto& entry : type->entries) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "ResourceTable.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
|
||||
using android::ConfigDescription;
|
||||
|
||||
@@ -144,6 +145,7 @@ static void CollapseVersions(int min_sdk, ResourceEntry* entry) {
|
||||
}
|
||||
|
||||
bool VersionCollapser::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
TRACE_NAME("VersionCollapser::Consume");
|
||||
const int min_sdk = context->GetMinSdkVersion();
|
||||
for (auto& package : table->packages) {
|
||||
for (auto& type : package->types) {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "Resource.h"
|
||||
#include "ResourceUtils.h"
|
||||
#include "ValueVisitor.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using ::android::ApkAssets;
|
||||
@@ -217,6 +218,7 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName(
|
||||
}
|
||||
|
||||
bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
|
||||
TRACE_CALL();
|
||||
if (std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path.data())) {
|
||||
apk_assets_.push_back(std::move(apk));
|
||||
|
||||
@@ -233,6 +235,7 @@ bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
|
||||
}
|
||||
|
||||
std::map<size_t, std::string> AssetManagerSymbolSource::GetAssignedPackageIds() const {
|
||||
TRACE_CALL();
|
||||
std::map<size_t, std::string> package_map;
|
||||
asset_manager_.ForEachPackage([&package_map](const std::string& name, uint8_t id) -> bool {
|
||||
package_map.insert(std::make_pair(id, name));
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "androidfw/ConfigDescription.h"
|
||||
|
||||
#include "ResourceTable.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using ::android::ConfigDescription;
|
||||
@@ -154,6 +155,7 @@ static void MarkNonPreferredDensitiesAsClaimed(
|
||||
}
|
||||
}
|
||||
bool TableSplitter::VerifySplitConstraints(IAaptContext* context) {
|
||||
TRACE_CALL();
|
||||
bool error = false;
|
||||
for (size_t i = 0; i < split_constraints_.size(); i++) {
|
||||
if (split_constraints_[i].configs.size() == 0) {
|
||||
|
||||
151
tools/aapt2/trace/TraceBuffer.cpp
Normal file
151
tools/aapt2/trace/TraceBuffer.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 "TraceBuffer.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "android-base/utf8.h"
|
||||
|
||||
#include "util/Files.h"
|
||||
|
||||
namespace aapt {
|
||||
namespace tracebuffer {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kBegin = 'B';
|
||||
constexpr char kEnd = 'E';
|
||||
|
||||
struct TracePoint {
|
||||
pid_t tid;
|
||||
int64_t time;
|
||||
std::string tag;
|
||||
char type;
|
||||
};
|
||||
|
||||
std::vector<TracePoint> traces;
|
||||
|
||||
int64_t GetTime() noexcept {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
void AddWithTime(const std::string& tag, char type, int64_t time) noexcept {
|
||||
TracePoint t = {getpid(), time, tag, type};
|
||||
traces.emplace_back(t);
|
||||
}
|
||||
|
||||
void Add(const std::string& tag, char type) noexcept {
|
||||
AddWithTime(tag, type, GetTime());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Flush(const std::string& basePath) {
|
||||
TRACE_CALL();
|
||||
if (basePath.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream s;
|
||||
s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json";
|
||||
FILE* f = android::base::utf8::fopen(s.str().c_str(), "a");
|
||||
if (f == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(const TracePoint& trace : traces) {
|
||||
fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", "
|
||||
"\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str());
|
||||
}
|
||||
fclose(f);
|
||||
traces.clear();
|
||||
}
|
||||
|
||||
} // namespace tracebuffer
|
||||
|
||||
void BeginTrace(const std::string& tag) {
|
||||
tracebuffer::Add(tag, tracebuffer::kBegin);
|
||||
}
|
||||
|
||||
void EndTrace() {
|
||||
tracebuffer::Add("", tracebuffer::kEnd);
|
||||
}
|
||||
|
||||
Trace::Trace(const std::string& tag) {
|
||||
tracebuffer::Add(tag, tracebuffer::kBegin);
|
||||
}
|
||||
|
||||
Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) {
|
||||
std::stringstream s;
|
||||
s << tag;
|
||||
s << " ";
|
||||
for (auto& arg : args) {
|
||||
s << arg.to_string();
|
||||
s << " ";
|
||||
}
|
||||
tracebuffer::Add(s.str(), tracebuffer::kBegin);
|
||||
}
|
||||
|
||||
Trace::~Trace() {
|
||||
tracebuffer::Add("", tracebuffer::kEnd);
|
||||
}
|
||||
|
||||
FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag)
|
||||
: basepath_(basepath) {
|
||||
tracebuffer::Add(tag, tracebuffer::kBegin);
|
||||
}
|
||||
|
||||
FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
|
||||
const std::vector<android::StringPiece>& args) : basepath_(basepath) {
|
||||
std::stringstream s;
|
||||
s << tag;
|
||||
s << " ";
|
||||
for (auto& arg : args) {
|
||||
s << arg.to_string();
|
||||
s << " ";
|
||||
}
|
||||
tracebuffer::Add(s.str(), tracebuffer::kBegin);
|
||||
}
|
||||
|
||||
FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
|
||||
const std::vector<std::string>& args) : basepath_(basepath){
|
||||
std::stringstream s;
|
||||
s << tag;
|
||||
s << " ";
|
||||
for (auto& arg : args) {
|
||||
s << arg;
|
||||
s << " ";
|
||||
}
|
||||
tracebuffer::Add(s.str(), tracebuffer::kBegin);
|
||||
}
|
||||
|
||||
FlushTrace::~FlushTrace() {
|
||||
tracebuffer::Add("", tracebuffer::kEnd);
|
||||
tracebuffer::Flush(basepath_);
|
||||
}
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
64
tools/aapt2/trace/TraceBuffer.h
Normal file
64
tools/aapt2/trace/TraceBuffer.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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_TRACEBUFFER_H
|
||||
#define AAPT_TRACEBUFFER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <androidfw/StringPiece.h>
|
||||
|
||||
namespace aapt {
|
||||
|
||||
// Record timestamps for beginning and end of a task and generate systrace json fragments.
|
||||
// This is an in-process ftrace which has the advantage of being platform independent.
|
||||
// These methods are NOT thread-safe since aapt2 is not multi-threaded.
|
||||
|
||||
// Convenience RIAA object to automatically finish an event when object goes out of scope.
|
||||
class Trace {
|
||||
public:
|
||||
Trace(const std::string& tag);
|
||||
Trace(const std::string& tag, const std::vector<android::StringPiece>& args);
|
||||
~Trace();
|
||||
};
|
||||
|
||||
// Manual markers.
|
||||
void BeginTrace(const std::string& tag);
|
||||
void EndTrace();
|
||||
|
||||
// A master trace is required to flush events to disk. Events are formatted in systrace
|
||||
// json format.
|
||||
class FlushTrace {
|
||||
public:
|
||||
explicit FlushTrace(const std::string& basepath, const std::string& tag);
|
||||
explicit FlushTrace(const std::string& basepath, const std::string& tag,
|
||||
const std::vector<android::StringPiece>& args);
|
||||
explicit FlushTrace(const std::string& basepath, const std::string& tag,
|
||||
const std::vector<std::string>& args);
|
||||
~FlushTrace();
|
||||
private:
|
||||
std::string basepath_;
|
||||
};
|
||||
|
||||
#define TRACE_CALL() Trace __t(__func__)
|
||||
#define TRACE_NAME(tag) Trace __t(tag)
|
||||
#define TRACE_NAME_ARGS(tag, args) Trace __t(tag, args)
|
||||
|
||||
#define TRACE_FLUSH(basename, tag) FlushTrace __t(basename, tag)
|
||||
#define TRACE_FLUSH_ARGS(basename, tag, args) FlushTrace __t(basename, tag, args)
|
||||
} // namespace aapt
|
||||
#endif //AAPT_TRACEBUFFER_H
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "android-base/logging.h"
|
||||
|
||||
#include "ResourceUtils.h"
|
||||
#include "trace/TraceBuffer.h"
|
||||
#include "XmlPullParser.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -264,6 +265,7 @@ static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPoo
|
||||
}
|
||||
|
||||
std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) {
|
||||
TRACE_CALL();
|
||||
// We import the android namespace because on Windows NO_ERROR is a macro, not
|
||||
// an enum, which causes errors when qualifying it with android::
|
||||
using namespace android;
|
||||
|
||||
Reference in New Issue
Block a user