blob: a3ec022021a00478db915d8f17823de8c3f9213e [file] [log] [blame]
// Copyright 2013 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 "content/browser/android/tracing_controller_android.h"
#include <string>
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/tracing_controller.h"
#include "jni/TracingControllerAndroidImpl_jni.h"
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using base::android::ScopedJavaGlobalRef;
namespace content {
static jlong JNI_TracingControllerAndroidImpl_Init(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
TracingControllerAndroid* profiler = new TracingControllerAndroid(env, obj);
return reinterpret_cast<intptr_t>(profiler);
}
TracingControllerAndroid::TracingControllerAndroid(JNIEnv* env, jobject obj)
: weak_java_object_(env, obj),
weak_factory_(this) {}
TracingControllerAndroid::~TracingControllerAndroid() {}
void TracingControllerAndroid::Destroy(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
delete this;
}
bool TracingControllerAndroid::StartTracing(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& jcategories,
const JavaParamRef<jstring>& jtraceoptions) {
std::string categories =
base::android::ConvertJavaStringToUTF8(env, jcategories);
std::string options =
base::android::ConvertJavaStringToUTF8(env, jtraceoptions);
// 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());
}
void TracingControllerAndroid::StopTracing(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& jfilepath,
bool compressfile,
const base::android::JavaParamRef<jobject>& callback) {
base::FilePath file_path(
base::android::ConvertJavaStringToUTF8(env, jfilepath));
ScopedJavaGlobalRef<jobject> global_callback(env, callback);
auto endpoint = TracingController::CreateFileEndpoint(
file_path,
base::BindRepeating(&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";
OnTracingStopped(global_callback);
}
}
void TracingControllerAndroid::GenerateTracingFilePath(
base::FilePath* file_path) {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> jfilename =
Java_TracingControllerAndroidImpl_generateTracingFilePath(env);
*file_path = base::FilePath(
base::android::ConvertJavaStringToUTF8(env, jfilename.obj()));
}
void TracingControllerAndroid::OnTracingStopped(
const base::android::ScopedJavaGlobalRef<jobject>& callback) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env);
if (obj.obj())
Java_TracingControllerAndroidImpl_onTracingStopped(env, obj, callback);
}
bool TracingControllerAndroid::GetKnownCategoriesAsync(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& callback) {
ScopedJavaGlobalRef<jobject> global_callback(env, callback);
return TracingController::GetInstance()->GetCategories(
base::BindOnce(&TracingControllerAndroid::OnKnownCategoriesReceived,
weak_factory_.GetWeakPtr(), global_callback));
}
void TracingControllerAndroid::OnKnownCategoriesReceived(
const ScopedJavaGlobalRef<jobject>& callback,
const std::set<std::string>& categories_received) {
base::ListValue category_list;
for (const std::string& category : categories_received)
category_list.AppendString(category);
std::string received_category_list;
base::JSONWriter::Write(category_list, &received_category_list);
// This log is required by adb_profile_chrome.py.
// TODO(crbug.com/898816): Replace (users of) this with DevTools' Tracing API.
LOG(WARNING) << "{\"traceCategoriesList\": " << received_category_list << "}";
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env);
if (obj.obj()) {
std::vector<std::string> category_vector(categories_received.begin(),
categories_received.end());
base::android::ScopedJavaLocalRef<jobjectArray> jcategories =
base::android::ToJavaArrayOfStrings(env, category_vector);
Java_TracingControllerAndroidImpl_onKnownCategoriesReceived(
env, obj, jcategories, callback);
}
}
static ScopedJavaLocalRef<jstring>
JNI_TracingControllerAndroidImpl_GetDefaultCategories(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
base::trace_event::TraceConfig trace_config;
return base::android::ConvertUTF8ToJavaString(
env, trace_config.ToCategoryFilterString());
}
bool TracingControllerAndroid::GetTraceBufferUsageAsync(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& callback) {
ScopedJavaGlobalRef<jobject> global_callback(env, callback);
return TracingController::GetInstance()->GetTraceBufferUsage(
base::BindOnce(&TracingControllerAndroid::OnTraceBufferUsageReceived,
weak_factory_.GetWeakPtr(), global_callback));
}
void TracingControllerAndroid::OnTraceBufferUsageReceived(
const ScopedJavaGlobalRef<jobject>& callback,
float percent_full,
size_t approximate_event_count) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env);
if (obj.obj()) {
Java_TracingControllerAndroidImpl_onTraceBufferUsageReceived(
env, obj, percent_full, approximate_event_count, callback);
}
}
} // namespace content