Commit 5d43def4 authored by ssid's avatar ssid Committed by Commit Bot

Support tracking location of post tasks in Android

Android task runner posts Runnable tasks and the tasks are run by native
task runner. All these tasks are recorded with posted location as
post_task_android.cc. To track the correct posted location, this cl adds
new trace events to track the runnable class name.
Note that we still track the wrapper task runner in some cases like
ChainedTasks and AsyncTask$NamedFutureTask, which needs to be fixed.

BUG=1136635

Change-Id: I97b35b003ce7d5571ce4a44c54127da74400cf1e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2480715
Commit-Queue: ssid <ssid@chromium.org>
Reviewed-by: default avatarTommy Nyquist <nyquist@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821378}
parent 9f3772ba
...@@ -94,7 +94,7 @@ public class PostTask { ...@@ -94,7 +94,7 @@ public class PostTask {
TaskTraits postedTraits = taskTraits.withExplicitDestination(); TaskTraits postedTraits = taskTraits.withExplicitDestination();
PostTaskJni.get().postDelayedTask(postedTraits.mPriority, postedTraits.mMayBlock, PostTaskJni.get().postDelayedTask(postedTraits.mPriority, postedTraits.mMayBlock,
postedTraits.mUseThreadPool, postedTraits.mExtensionId, postedTraits.mUseThreadPool, postedTraits.mExtensionId,
postedTraits.mExtensionData, task, delay); postedTraits.mExtensionData, task, delay, task.getClass().getName());
} }
} }
...@@ -269,6 +269,7 @@ public class PostTask { ...@@ -269,6 +269,7 @@ public class PostTask {
@NativeMethods @NativeMethods
interface Natives { interface Natives {
void postDelayedTask(int priority, boolean mayBlock, boolean useThreadPool, void postDelayedTask(int priority, boolean mayBlock, boolean useThreadPool,
byte extensionId, byte[] extensionData, Runnable task, long delay); byte extensionId, byte[] extensionData, Runnable task, long delay,
String runnableClassName);
} }
} }
...@@ -131,13 +131,15 @@ public class TaskRunnerImpl implements TaskRunner { ...@@ -131,13 +131,15 @@ public class TaskRunnerImpl implements TaskRunner {
public void postDelayedTask(Runnable task, long delay) { public void postDelayedTask(Runnable task, long delay) {
// Lock-free path when native is initialized. // Lock-free path when native is initialized.
if (mNativeTaskRunnerAndroid != 0) { if (mNativeTaskRunnerAndroid != 0) {
TaskRunnerImplJni.get().postDelayedTask(mNativeTaskRunnerAndroid, task, delay); TaskRunnerImplJni.get().postDelayedTask(
mNativeTaskRunnerAndroid, task, delay, task.getClass().getName());
return; return;
} }
synchronized (mPreNativeTaskLock) { synchronized (mPreNativeTaskLock) {
oneTimeInitialization(); oneTimeInitialization();
if (mNativeTaskRunnerAndroid != 0) { if (mNativeTaskRunnerAndroid != 0) {
TaskRunnerImplJni.get().postDelayedTask(mNativeTaskRunnerAndroid, task, delay); TaskRunnerImplJni.get().postDelayedTask(
mNativeTaskRunnerAndroid, task, delay, task.getClass().getName());
return; return;
} }
// We don't expect a whole lot of these, if that changes consider pooling them. // We don't expect a whole lot of these, if that changes consider pooling them.
...@@ -224,14 +226,15 @@ public class TaskRunnerImpl implements TaskRunner { ...@@ -224,14 +226,15 @@ public class TaskRunnerImpl implements TaskRunner {
synchronized (mPreNativeTaskLock) { synchronized (mPreNativeTaskLock) {
if (mPreNativeTasks != null) { if (mPreNativeTasks != null) {
for (Runnable task : mPreNativeTasks) { for (Runnable task : mPreNativeTasks) {
TaskRunnerImplJni.get().postDelayedTask(nativeTaskRunnerAndroid, task, 0); TaskRunnerImplJni.get().postDelayedTask(
nativeTaskRunnerAndroid, task, 0, task.getClass().getName());
} }
mPreNativeTasks = null; mPreNativeTasks = null;
} }
if (mPreNativeDelayedTasks != null) { if (mPreNativeDelayedTasks != null) {
for (Pair<Runnable, Long> task : mPreNativeDelayedTasks) { for (Pair<Runnable, Long> task : mPreNativeDelayedTasks) {
TaskRunnerImplJni.get().postDelayedTask( TaskRunnerImplJni.get().postDelayedTask(nativeTaskRunnerAndroid, task.first,
nativeTaskRunnerAndroid, task.first, task.second); task.second, task.getClass().getName());
} }
mPreNativeDelayedTasks = null; mPreNativeDelayedTasks = null;
} }
...@@ -259,7 +262,8 @@ public class TaskRunnerImpl implements TaskRunner { ...@@ -259,7 +262,8 @@ public class TaskRunnerImpl implements TaskRunner {
boolean useThreadPool, byte extensionId, byte[] extensionData); boolean useThreadPool, byte extensionId, byte[] extensionData);
void destroy(long nativeTaskRunnerAndroid); void destroy(long nativeTaskRunnerAndroid);
void postDelayedTask(long nativeTaskRunnerAndroid, Runnable task, long delay); void postDelayedTask(
long nativeTaskRunnerAndroid, Runnable task, long delay, String runnableClassName);
boolean belongsToCurrentThread(long nativeTaskRunnerAndroid); boolean belongsToCurrentThread(long nativeTaskRunnerAndroid);
} }
} }
...@@ -4,12 +4,15 @@ ...@@ -4,12 +4,15 @@
#include "base/android/task_scheduler/post_task_android.h" #include "base/android/task_scheduler/post_task_android.h"
#include "base/android/jni_string.h"
#include "base/android_runtime_jni_headers/Runnable_jni.h" #include "base/android_runtime_jni_headers/Runnable_jni.h"
#include "base/base_jni_headers/PostTask_jni.h" #include "base/base_jni_headers/PostTask_jni.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool_instance.h" #include "base/task/thread_pool/thread_pool_instance.h"
#include "base/trace_event/base_tracing.h"
namespace base { namespace base {
...@@ -65,24 +68,35 @@ void JNI_PostTask_PostDelayedTask( ...@@ -65,24 +68,35 @@ void JNI_PostTask_PostDelayedTask(
jbyte extension_id, jbyte extension_id,
const base::android::JavaParamRef<jbyteArray>& extension_data, const base::android::JavaParamRef<jbyteArray>& extension_data,
const base::android::JavaParamRef<jobject>& task, const base::android::JavaParamRef<jobject>& task,
jlong delay) { jlong delay,
const base::android::JavaParamRef<jstring>& runnable_class_name) {
// This could be run on any java thread, so we can't cache |env| in the // This could be run on any java thread, so we can't cache |env| in the
// BindOnce because JNIEnv is thread specific. // BindOnce because JNIEnv is thread specific.
PostDelayedTask(FROM_HERE, PostDelayedTask(
PostTaskAndroid::CreateTaskTraits( FROM_HERE,
env, priority, may_block, use_thread_pool, extension_id, PostTaskAndroid::CreateTaskTraits(env, priority, may_block,
extension_data), use_thread_pool, extension_id,
BindOnce(&PostTaskAndroid::RunJavaTask, extension_data),
base::android::ScopedJavaGlobalRef<jobject>(task)), BindOnce(&PostTaskAndroid::RunJavaTask,
TimeDelta::FromMilliseconds(delay)); base::android::ScopedJavaGlobalRef<jobject>(task),
android::ConvertJavaStringToUTF8(runnable_class_name)),
TimeDelta::FromMilliseconds(delay));
} }
// static // static
void PostTaskAndroid::RunJavaTask( void PostTaskAndroid::RunJavaTask(
base::android::ScopedJavaGlobalRef<jobject> task) { base::android::ScopedJavaGlobalRef<jobject> task,
const std::string& runnable_class_name) {
// JNIEnv is thread specific, but we don't know which thread we'll be run on // JNIEnv is thread specific, but we don't know which thread we'll be run on
// so we must look it up. // so we must look it up.
std::string event_name = base::StrCat({"JniPostTask: ", runnable_class_name});
TRACE_EVENT_BEGIN_WITH_FLAGS0(
"toplevel", event_name.c_str(),
TRACE_EVENT_FLAG_JAVA_STRING_LITERALS | TRACE_EVENT_FLAG_COPY);
JNI_Runnable::Java_Runnable_run(base::android::AttachCurrentThread(), task); JNI_Runnable::Java_Runnable_run(base::android::AttachCurrentThread(), task);
TRACE_EVENT_END_WITH_FLAGS0(
"toplevel", event_name.c_str(),
TRACE_EVENT_FLAG_JAVA_STRING_LITERALS | TRACE_EVENT_FLAG_COPY);
} }
} // namespace base } // namespace base
...@@ -32,7 +32,8 @@ class BASE_EXPORT PostTaskAndroid { ...@@ -32,7 +32,8 @@ class BASE_EXPORT PostTaskAndroid {
// We don't know ahead of time which thread this will run on so it looks up // We don't know ahead of time which thread this will run on so it looks up
// the JNI environment and the bindings dynamically (albeit with caching). // the JNI environment and the bindings dynamically (albeit with caching).
static void RunJavaTask(base::android::ScopedJavaGlobalRef<jobject> task); static void RunJavaTask(base::android::ScopedJavaGlobalRef<jobject> task,
const std::string& runnable_class_name);
DISALLOW_COPY_AND_ASSIGN(PostTaskAndroid); DISALLOW_COPY_AND_ASSIGN(PostTaskAndroid);
}; };
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "base/android/task_scheduler/task_runner_android.h" #include "base/android/task_scheduler/task_runner_android.h"
#include "base/android/jni_string.h"
#include "base/android/task_scheduler/post_task_android.h" #include "base/android/task_scheduler/post_task_android.h"
#include "base/base_jni_headers/TaskRunnerImpl_jni.h" #include "base/base_jni_headers/TaskRunnerImpl_jni.h"
#include "base/bind.h" #include "base/bind.h"
...@@ -53,11 +54,14 @@ void TaskRunnerAndroid::Destroy(JNIEnv* env) { ...@@ -53,11 +54,14 @@ void TaskRunnerAndroid::Destroy(JNIEnv* env) {
void TaskRunnerAndroid::PostDelayedTask( void TaskRunnerAndroid::PostDelayedTask(
JNIEnv* env, JNIEnv* env,
const base::android::JavaRef<jobject>& task, const base::android::JavaRef<jobject>& task,
jlong delay) { jlong delay,
jstring runnable_class_name) {
task_runner_->PostDelayedTask( task_runner_->PostDelayedTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&PostTaskAndroid::RunJavaTask, base::BindOnce(
base::android::ScopedJavaGlobalRef<jobject>(task)), &PostTaskAndroid::RunJavaTask,
base::android::ScopedJavaGlobalRef<jobject>(task),
android::ConvertJavaStringToUTF8(env, runnable_class_name)),
TimeDelta::FromMilliseconds(delay)); TimeDelta::FromMilliseconds(delay));
} }
......
...@@ -25,7 +25,8 @@ class TaskRunnerAndroid { ...@@ -25,7 +25,8 @@ class TaskRunnerAndroid {
void PostDelayedTask(JNIEnv* env, void PostDelayedTask(JNIEnv* env,
const base::android::JavaRef<jobject>& task, const base::android::JavaRef<jobject>& task,
jlong delay); jlong delay,
jstring runnable_class_name);
bool BelongsToCurrentThread(JNIEnv* env); bool BelongsToCurrentThread(JNIEnv* env);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment