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
This commit is contained in:
Adam Barth 2015-01-15 16:32:16 -08:00
parent de266a6ba7
commit 656c44bafb
4 changed files with 122 additions and 10 deletions

View File

@ -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",

View File

@ -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 <algorithm>
#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<net::HttpServer> web_server_;
uint32_t command_port_;
scoped_ptr<TraceCollector> trace_collector_;
DISALLOW_COPY_AND_ASSIGN(Prompt);
};

View File

@ -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<const char*>(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

View File

@ -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 <vector>
#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<void(std::string)> 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<char> trace_;
bool is_complete_;
TraceCallback callback_;
};
} // namespace debugger
} // namespace sky
#endif // SKY_TOOLS_DEBUGGER_PROMPT_TRACE_COLLECTOR_H_