android: Add the target to toplevel Looper events in tracing.

When tracing is enabled, toplevel Looper tasks come from Chrome and the
system. Non-native tasks are a black box, as they only show up as
"toplevel.dispatchMessage" in tracing. This commit adds the "target" of
the looper task as a parameter in the trace.

For instance (from a startup trace):
- android.view.ViewRootImpl$ViewRootHandler
- android.view.Choreographer$FrameHandler
- android.os.AsyncTask$InternalHandler
- com.google.android.gms.common.internal.s

This allows to distinguish between framework time, Chrome's Java tasks
and third-party libs (GMSCore above).

About performance cost:
- The Java string is already created by the framework code, we extract a
  substring of it.
- A new parameter for each toplevel trace event.

Review-Url: https://codereview.chromium.org/2883993002
Cr-Commit-Position: refs/heads/master@{#472043}


CrOS-Libchrome-Original-Commit: 71be2dc15e6765170cbc0054bb12fec403b9bed3
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java
index 71bfac1..b2f9782 100644
--- a/base/android/java/src/org/chromium/base/TraceEvent.java
+++ b/base/android/java/src/org/chromium/base/TraceEvent.java
@@ -38,7 +38,14 @@
         }
 
         void beginHandling(final String line) {
-            if (sEnabled) nativeBeginToplevel();
+            if (sEnabled) {
+                // Android Looper formats |line| as ">>>>> Dispatching to (TARGET) [...]" since at
+                // least 2009 (Donut). Extracts the TARGET part of the message.
+                int start = line.indexOf('(', 21); // strlen(">>>>> Dispatching to ")
+                int end = start == -1 ? -1 : line.indexOf(')', start);
+                String target = end != -1 ? line.substring(start + 1, end) : "";
+                nativeBeginToplevel(target);
+            }
         }
 
         void endHandling(final String line) {
@@ -307,7 +314,7 @@
     private static native void nativeInstant(String name, String arg);
     private static native void nativeBegin(String name, String arg);
     private static native void nativeEnd(String name, String arg);
-    private static native void nativeBeginToplevel();
+    private static native void nativeBeginToplevel(String target);
     private static native void nativeEndToplevel();
     private static native void nativeStartAsync(String name, long id);
     private static native void nativeFinishAsync(String name, long id);
diff --git a/base/android/trace_event_binding.cc b/base/android/trace_event_binding.cc
index 8551f99..30ca55e 100644
--- a/base/android/trace_event_binding.cc
+++ b/base/android/trace_event_binding.cc
@@ -121,8 +121,12 @@
   }
 }
 
-static void BeginToplevel(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
-  TRACE_EVENT_BEGIN0(kToplevelCategory, kLooperDispatchMessage);
+static void BeginToplevel(JNIEnv* env,
+                          const JavaParamRef<jclass>& clazz,
+                          const JavaParamRef<jstring>& jtarget) {
+  std::string target = ConvertJavaStringToUTF8(env, jtarget);
+  TRACE_EVENT_BEGIN1(kToplevelCategory, kLooperDispatchMessage, "target",
+                     target);
 }
 
 static void EndToplevel(JNIEnv* env, const JavaParamRef<jclass>& clazz) {