diff options
Diffstat (limited to 'chromium/content/browser/android/tracing_controller_android.cc')
-rw-r--r-- | chromium/content/browser/android/tracing_controller_android.cc | 136 |
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( |