summaryrefslogtreecommitdiff
path: root/chromium/content/browser/android/tracing_controller_android.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/android/tracing_controller_android.cc')
-rw-r--r--chromium/content/browser/android/tracing_controller_android.cc136
1 files changed, 123 insertions, 13 deletions
diff --git a/chromium/content/browser/android/tracing_controller_android.cc b/chromium/content/browser/android/tracing_controller_android.cc
index 9c6c152f726..b1dcbc8dae6 100644
--- a/chromium/content/browser/android/tracing_controller_android.cc
+++ b/chromium/content/browser/android/tracing_controller_android.cc
@@ -16,12 +16,56 @@
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/android/content_jni_headers/TracingControllerAndroidImpl_jni.h"
#include "content/public/browser/tracing_controller.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_session.h"
+#include "services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
+#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
+#include "third_party/perfetto/protos/perfetto/common/trace_stats.gen.h"
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using base::android::ScopedJavaGlobalRef;
namespace content {
+namespace {
+
+// Currently active tracing session.
+perfetto::TracingSession* g_tracing_session = nullptr;
+
+void ReadProtobufTraceData(
+ scoped_refptr<TracingController::TraceDataEndpoint> endpoint,
+ perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ if (args.size) {
+ auto data_string = std::make_unique<std::string>(args.data, args.size);
+ endpoint->ReceiveTraceChunk(std::move(data_string));
+ }
+ if (!args.has_more)
+ endpoint->ReceivedTraceFinalContents();
+}
+
+void ReadJsonTraceData(
+ scoped_refptr<TracingController::TraceDataEndpoint> endpoint,
+ tracing::TracePacketTokenizer& tokenizer,
+ perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ if (args.size) {
+ auto packets =
+ tokenizer.Parse(reinterpret_cast<const uint8_t*>(args.data), args.size);
+ for (const auto& packet : packets) {
+ for (const auto& slice : packet.slices()) {
+ auto data_string = std::make_unique<std::string>(
+ reinterpret_cast<const char*>(slice.start), slice.size);
+ endpoint->ReceiveTraceChunk(std::move(data_string));
+ }
+ }
+ }
+ if (!args.has_more) {
+ DCHECK(!tokenizer.has_more());
+ endpoint->ReceivedTraceFinalContents();
+ }
+}
+
+} // namespace
static jlong JNI_TracingControllerAndroidImpl_Init(
JNIEnv* env,
@@ -44,7 +88,8 @@ bool TracingControllerAndroid::StartTracing(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& jcategories,
- const JavaParamRef<jstring>& jtraceoptions) {
+ const JavaParamRef<jstring>& jtraceoptions,
+ bool use_protobuf) {
std::string categories =
base::android::ConvertJavaStringToUTF8(env, jcategories);
std::string options =
@@ -53,16 +98,23 @@ bool TracingControllerAndroid::StartTracing(
// This log is required by adb_profile_chrome.py.
LOG(WARNING) << "Logging performance trace to file";
- return TracingController::GetInstance()->StartTracing(
- base::trace_event::TraceConfig(categories, options),
- TracingController::StartTracingDoneCallback());
+ base::trace_event::TraceConfig trace_config(categories, options);
+ perfetto::TraceConfig perfetto_config = tracing::GetDefaultPerfettoConfig(
+ base::trace_event::TraceConfig(), /*privacy_filtering_enabled=*/false,
+ /*convert_to_legacy_json=*/!use_protobuf);
+ delete g_tracing_session;
+ g_tracing_session = perfetto::Tracing::NewTrace().release();
+ g_tracing_session->Setup(perfetto_config);
+ g_tracing_session->Start();
+ return true;
}
void TracingControllerAndroid::StopTracing(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& jfilepath,
- bool compressfile,
+ bool compress_file,
+ bool use_protobuf,
const base::android::JavaParamRef<jobject>& callback) {
base::FilePath file_path(
base::android::ConvertJavaStringToUTF8(env, jfilepath));
@@ -70,14 +122,43 @@ void TracingControllerAndroid::StopTracing(
auto endpoint = TracingController::CreateFileEndpoint(
file_path, base::BindOnce(&TracingControllerAndroid::OnTracingStopped,
weak_factory_.GetWeakPtr(), global_callback));
- if (compressfile) {
- endpoint =
- TracingControllerImpl::CreateCompressedStringEndpoint(endpoint, true);
- }
- if (!TracingController::GetInstance()->StopTracing(endpoint)) {
- LOG(ERROR) << "EndTracingAsync failed, forcing an immediate stop";
+
+ if (!g_tracing_session) {
+ LOG(ERROR) << "Tried to stop a non-existent tracing session";
OnTracingStopped(global_callback);
+ return;
+ }
+
+ if (compress_file) {
+ endpoint = TracingControllerImpl::CreateCompressedStringEndpoint(
+ endpoint, /*compress_with_background_priority=*/true);
+ }
+
+ auto session = base::MakeRefCounted<
+ base::RefCountedData<std::unique_ptr<perfetto::TracingSession>>>(
+ base::WrapUnique(g_tracing_session));
+ g_tracing_session = nullptr;
+ if (use_protobuf) {
+ session->data->SetOnStopCallback([session, endpoint] {
+ session->data->ReadTrace(
+ [session,
+ endpoint](perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ ReadProtobufTraceData(endpoint, args);
+ });
+ });
+ } else {
+ auto tokenizer = base::MakeRefCounted<
+ base::RefCountedData<std::unique_ptr<tracing::TracePacketTokenizer>>>(
+ std::make_unique<tracing::TracePacketTokenizer>());
+ session->data->SetOnStopCallback([session, tokenizer, endpoint] {
+ session->data->ReadTrace(
+ [session, tokenizer,
+ endpoint](perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ ReadJsonTraceData(endpoint, *tokenizer->data, args);
+ });
+ });
}
+ session->data->Stop();
}
void TracingControllerAndroid::GenerateTracingFilePath(
@@ -102,6 +183,7 @@ bool TracingControllerAndroid::GetKnownCategoriesAsync(
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& callback) {
ScopedJavaGlobalRef<jobject> global_callback(env, callback);
+ // TODO(skyostil): Get the categories from Perfetto instead.
return TracingController::GetInstance()->GetCategories(
base::BindOnce(&TracingControllerAndroid::OnKnownCategoriesReceived,
weak_factory_.GetWeakPtr(), global_callback));
@@ -146,9 +228,37 @@ bool TracingControllerAndroid::GetTraceBufferUsageAsync(
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& callback) {
ScopedJavaGlobalRef<jobject> global_callback(env, callback);
- return TracingController::GetInstance()->GetTraceBufferUsage(
+ auto weak_callback =
base::BindOnce(&TracingControllerAndroid::OnTraceBufferUsageReceived,
- weak_factory_.GetWeakPtr(), global_callback));
+ weak_factory_.GetWeakPtr(), global_callback);
+
+ if (!g_tracing_session) {
+ std::move(weak_callback)
+ .Run(/*percent_full=*/0.f, /*approximate_event_count=*/0);
+ return true;
+ }
+
+ // |weak_callback| is move-only, so in order to pass it through a copied
+ // lambda we need to temporarily move it on the heap.
+ auto shared_callback = base::MakeRefCounted<
+ base::RefCountedData<base::OnceCallback<void(float, size_t)>>>(
+ std::move(weak_callback));
+ g_tracing_session->GetTraceStats(
+ [shared_callback](
+ perfetto::TracingSession::GetTraceStatsCallbackArgs args) {
+ float percent_full = 0;
+ perfetto::protos::gen::TraceStats trace_stats;
+ if (args.success &&
+ trace_stats.ParseFromArray(args.trace_stats_data.data(),
+ args.trace_stats_data.size())) {
+ percent_full = tracing::GetTraceBufferUsage(trace_stats);
+ }
+ // TODO(skyostil): Remove approximate_event_count since no-one is using
+ // it.
+ std::move(shared_callback->data)
+ .Run(percent_full, /*approximate_event_count=*/0);
+ });
+ return true;
}
void TracingControllerAndroid::OnTraceBufferUsageReceived(