From 656c44bafb1b44dc8aaeddb0501637a60d858f7c Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 15 Jan 2015 16:32:16 -0800 Subject: [PATCH] Make tracing work on Android Previously, the trace coordinator would try to write a trace to the file system, but it is awkward to write to the file system on Android. Instead, we now stream the trace data to a data pipe. The Sky debugger consumes that data pipe and sends it to the host via the command HTTP server. R=eseidel@chromium.org, jamesr@chromium.org Review URL: https://codereview.chromium.org/853943005 --- .../flutter/tools/debugger/prompt/BUILD.gn | 4 ++ .../flutter/tools/debugger/prompt/prompt.cc | 44 ++++++++++++++----- .../tools/debugger/prompt/trace_collector.cc | 44 +++++++++++++++++++ .../tools/debugger/prompt/trace_collector.h | 40 +++++++++++++++++ 4 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 engine/src/flutter/tools/debugger/prompt/trace_collector.cc create mode 100644 engine/src/flutter/tools/debugger/prompt/trace_collector.h diff --git a/engine/src/flutter/tools/debugger/prompt/BUILD.gn b/engine/src/flutter/tools/debugger/prompt/BUILD.gn index 578d976b67..59848f19e9 100644 --- a/engine/src/flutter/tools/debugger/prompt/BUILD.gn +++ b/engine/src/flutter/tools/debugger/prompt/BUILD.gn @@ -9,12 +9,16 @@ mojo_native_application("prompt") { sources = [ "prompt.cc", + "trace_collector.cc", + "trace_collector.h", ] deps = [ "//base", "//mojo/application", + "//mojo/common", "//mojo/public/cpp/bindings", + "//mojo/public/cpp/system", "//mojo/public/cpp/utility", "//net", "//net:http_server", diff --git a/engine/src/flutter/tools/debugger/prompt/prompt.cc b/engine/src/flutter/tools/debugger/prompt/prompt.cc index e31233646f..1c7154eb84 100644 --- a/engine/src/flutter/tools/debugger/prompt/prompt.cc +++ b/engine/src/flutter/tools/debugger/prompt/prompt.cc @@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "base/bind.h" +#include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -16,11 +19,17 @@ #include "net/socket/tcp_server_socket.h" #include "services/tracing/tracing.mojom.h" #include "sky/tools/debugger/debugger.mojom.h" +#include "sky/tools/debugger/prompt/trace_collector.h" namespace sky { namespace debugger { +namespace { -class Prompt : public mojo::ApplicationDelegate, public net::HttpServer::Delegate { +const size_t kMinSendBufferSize = 1024 * 1024; +} + +class Prompt : public mojo::ApplicationDelegate, + public net::HttpServer::Delegate { public: Prompt() : is_tracing_(false), @@ -98,6 +107,10 @@ class Prompt : public mojo::ApplicationDelegate, public net::HttpServer::Delegat } void Respond(int connection_id, std::string response) { + // When sending tracing data back over the wire to the client, we can blow + // through the default send buffer size. + web_server_->SetSendBufferSize( + connection_id, std::max(kMinSendBufferSize, response.length())); web_server_->Send200(connection_id, response, "text/plain"); } @@ -138,16 +151,25 @@ class Prompt : public mojo::ApplicationDelegate, public net::HttpServer::Delegat } void ToggleTracing(int connection_id) { - std::string response; - if (is_tracing_) { - response = "Stopping trace (writing to sky_viewer.trace)\n"; - tracing_->StopAndFlush(); - } else { - response = "Starting trace (type 'trace' to stop tracing)\n"; - tracing_->Start(mojo::String("sky_viewer"), mojo::String("*")); - } + bool was_tracing = is_tracing_; is_tracing_ = !is_tracing_; - Respond(connection_id, response); + + if (was_tracing) { + tracing_->StopAndFlush(); + trace_collector_->GetTrace(base::Bind( + &Prompt::OnTraceAvailable, base::Unretained(this), connection_id)); + return; + } + + mojo::DataPipe pipe; + tracing_->Start(pipe.producer_handle.Pass(), mojo::String("*")); + trace_collector_.reset(new TraceCollector(pipe.consumer_handle.Pass())); + Respond(connection_id, "Starting trace (type 'trace' to stop tracing)\n"); + } + + void OnTraceAvailable(int connection_id, std::string trace) { + trace_collector_.reset(); + Respond(connection_id, trace); } bool is_tracing_; @@ -158,6 +180,8 @@ class Prompt : public mojo::ApplicationDelegate, public net::HttpServer::Delegat scoped_ptr web_server_; uint32_t command_port_; + scoped_ptr trace_collector_; + DISALLOW_COPY_AND_ASSIGN(Prompt); }; diff --git a/engine/src/flutter/tools/debugger/prompt/trace_collector.cc b/engine/src/flutter/tools/debugger/prompt/trace_collector.cc new file mode 100644 index 0000000000..09481825d4 --- /dev/null +++ b/engine/src/flutter/tools/debugger/prompt/trace_collector.cc @@ -0,0 +1,44 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/tools/debugger/prompt/trace_collector.h" + +namespace sky { +namespace debugger { + +TraceCollector::TraceCollector(mojo::ScopedDataPipeConsumerHandle source) + : drainer_(this, source.Pass()), is_complete_(false) { +} + +TraceCollector::~TraceCollector() { +} + +void TraceCollector::GetTrace(TraceCallback callback) { + DCHECK(!callback_.is_null()); + if (is_complete_) { + callback.Run(GetTraceAsString()); + return; + } + callback_ = callback; +} + +void TraceCollector::OnDataAvailable(const void* data, size_t num_bytes) { + DCHECK(!is_complete_); + const char* chars = static_cast(data); + trace_.insert(trace_.end(), chars, chars + num_bytes); +} + +void TraceCollector::OnDataComplete() { + DCHECK(!is_complete_); + is_complete_ = true; + if (!callback_.is_null()) + callback_.Run(GetTraceAsString()); +} + +std::string TraceCollector::GetTraceAsString() { + return std::string(&trace_.front(), trace_.size()); +} + +} // namespace debugger +} // namespace sky diff --git a/engine/src/flutter/tools/debugger/prompt/trace_collector.h b/engine/src/flutter/tools/debugger/prompt/trace_collector.h new file mode 100644 index 0000000000..773a402144 --- /dev/null +++ b/engine/src/flutter/tools/debugger/prompt/trace_collector.h @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_TOOLS_DEBUGGER_PROMPT_TRACE_COLLECTOR_H_ +#define SKY_TOOLS_DEBUGGER_PROMPT_TRACE_COLLECTOR_H_ + +#include + +#include "base/callback.h" +#include "mojo/common/data_pipe_drainer.h" + +namespace sky { +namespace debugger { + +class TraceCollector : public mojo::common::DataPipeDrainer::Client { + public: + typedef base::Callback TraceCallback; + + explicit TraceCollector(mojo::ScopedDataPipeConsumerHandle source); + ~TraceCollector(); + + void GetTrace(TraceCallback callback); + + private: + void OnDataAvailable(const void* data, size_t num_bytes) override; + void OnDataComplete() override; + + std::string GetTraceAsString(); + + mojo::common::DataPipeDrainer drainer_; + std::vector trace_; + bool is_complete_; + TraceCallback callback_; +}; + +} // namespace debugger +} // namespace sky + +#endif // SKY_TOOLS_DEBUGGER_PROMPT_TRACE_COLLECTOR_H_