This source file includes following definitions.
- JNINamespace
- println
- beginHandling
- endHandling
- syncIdleMonitoring
- beginHandling
- endHandling
- traceAndLog
- queueIdle
- setEnabledToMatchNative
- setATraceEnabled
- enabled
- instant
- instant
- startAsync
- startAsync
- startAsync
- finishAsync
- finishAsync
- finishAsync
- begin
- begin
- begin
- end
- end
- end
- getCallerName
- nativeTraceEnabled
- nativeStartATrace
- nativeStopATrace
- nativeInstant
- nativeBegin
- nativeEnd
- nativeStartAsync
- nativeFinishAsync
package org.chromium.base;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.SystemClock;
import android.util.Log;
import android.util.Printer;
@JNINamespace("base::android")
public class TraceEvent {
private static volatile boolean sEnabled = false;
private static class BasicLooperMonitor implements Printer {
private static final String DISPATCH_EVENT_NAME =
"Looper.dispatchMessage";
@Override
public void println(final String line) {
if (line.startsWith(">")) {
beginHandling(line);
} else {
assert line.startsWith("<");
endHandling(line);
}
}
void beginHandling(final String line) {
TraceEvent.begin(DISPATCH_EVENT_NAME, line);
}
void endHandling(final String line) {
TraceEvent.end(DISPATCH_EVENT_NAME);
}
}
private static final class IdleTracingLooperMonitor extends BasicLooperMonitor
implements MessageQueue.IdleHandler {
private static final String TAG = "TraceEvent.LooperMonitor";
private static final String IDLE_EVENT_NAME = "Looper.queueIdle";
private static final long FRAME_DURATION_MILLIS = 1000L / 60L;
private static final long MIN_INTERESTING_DURATION_MILLIS =
FRAME_DURATION_MILLIS;
private static final long MIN_INTERESTING_BURST_DURATION_MILLIS =
MIN_INTERESTING_DURATION_MILLIS * 3;
private long mLastIdleStartedAt = 0L;
private long mLastWorkStartedAt = 0L;
private int mNumTasksSeen = 0;
private int mNumIdlesSeen = 0;
private int mNumTasksSinceLastIdle = 0;
private boolean mIdleMonitorAttached = false;
private final void syncIdleMonitoring() {
if (sEnabled && !mIdleMonitorAttached) {
mLastIdleStartedAt = SystemClock.elapsedRealtime();
Looper.myQueue().addIdleHandler(this);
mIdleMonitorAttached = true;
Log.v(TAG, "attached idle handler");
} else if (mIdleMonitorAttached && !sEnabled) {
Looper.myQueue().removeIdleHandler(this);
mIdleMonitorAttached = false;
Log.v(TAG, "detached idle handler");
}
}
@Override
final void beginHandling(final String line) {
if (mNumTasksSinceLastIdle == 0) {
TraceEvent.end(IDLE_EVENT_NAME);
}
mLastWorkStartedAt = SystemClock.elapsedRealtime();
syncIdleMonitoring();
super.beginHandling(line);
}
@Override
final void endHandling(final String line) {
final long elapsed = SystemClock.elapsedRealtime()
- mLastWorkStartedAt;
if (elapsed > MIN_INTERESTING_DURATION_MILLIS) {
traceAndLog(Log.WARN, "observed a task that took "
+ elapsed + "ms: " + line);
}
super.endHandling(line);
syncIdleMonitoring();
mNumTasksSeen++;
mNumTasksSinceLastIdle++;
}
private static void traceAndLog(int level, String message) {
TraceEvent.instant("TraceEvent.LooperMonitor:IdleStats", message);
Log.println(level, TAG, message);
}
@Override
public final boolean queueIdle() {
final long now = SystemClock.elapsedRealtime();
if (mLastIdleStartedAt == 0) mLastIdleStartedAt = now;
final long elapsed = now - mLastIdleStartedAt;
mNumIdlesSeen++;
TraceEvent.begin(IDLE_EVENT_NAME, mNumTasksSinceLastIdle + " tasks since last idle.");
if (elapsed > MIN_INTERESTING_BURST_DURATION_MILLIS) {
String statsString = mNumTasksSeen + " tasks and "
+ mNumIdlesSeen + " idles processed so far, "
+ mNumTasksSinceLastIdle + " tasks bursted and "
+ elapsed + "ms elapsed since last idle";
traceAndLog(Log.DEBUG, statsString);
}
mLastIdleStartedAt = now;
mNumTasksSinceLastIdle = 0;
return true;
}
}
private static final class LooperMonitorHolder {
private static final BasicLooperMonitor sInstance =
CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_IDLE_TRACING) ?
new IdleTracingLooperMonitor() : new BasicLooperMonitor();
}
public static void setEnabledToMatchNative() {
boolean enabled = nativeTraceEnabled();
if (sEnabled == enabled) return;
sEnabled = enabled;
ThreadUtils.getUiThreadLooper().setMessageLogging(
enabled() ? LooperMonitorHolder.sInstance : null);
}
public static void setATraceEnabled(boolean enabled) {
if (enabled) {
nativeStartATrace();
} else {
nativeStopATrace();
}
setEnabledToMatchNative();
}
public static boolean enabled() {
return sEnabled;
}
public static void instant(String name) {
if (sEnabled) nativeInstant(name, null);
}
public static void instant(String name, String arg) {
if (sEnabled) nativeInstant(name, arg);
}
public static void startAsync(long id) {
if (sEnabled) nativeStartAsync(getCallerName(), id, null);
}
public static void startAsync(String name, long id) {
if (sEnabled) nativeStartAsync(name, id, null);
}
public static void startAsync(String name, long id, String arg) {
if (sEnabled) nativeStartAsync(name, id, arg);
}
public static void finishAsync(long id) {
if (sEnabled) nativeFinishAsync(getCallerName(), id, null);
}
public static void finishAsync(String name, long id) {
if (sEnabled) nativeFinishAsync(name, id, null);
}
public static void finishAsync(String name, long id, String arg) {
if (sEnabled) nativeFinishAsync(name, id, arg);
}
public static void begin() {
if (sEnabled) nativeBegin(getCallerName(), null);
}
public static void begin(String name) {
if (sEnabled) nativeBegin(name, null);
}
public static void begin(String name, String arg) {
if (sEnabled) nativeBegin(name, arg);
}
public static void end() {
if (sEnabled) nativeEnd(getCallerName(), null);
}
public static void end(String name) {
if (sEnabled) nativeEnd(name, null);
}
public static void end(String name, String arg) {
if (sEnabled) nativeEnd(name, arg);
}
private static String getCallerName() {
StackTraceElement[] stack = java.lang.Thread.currentThread().getStackTrace();
return stack[4].getClassName() + "." + stack[4].getMethodName();
}
private static native boolean nativeTraceEnabled();
private static native void nativeStartATrace();
private static native void nativeStopATrace();
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 nativeStartAsync(String name, long id, String arg);
private static native void nativeFinishAsync(String name, long id, String arg);
}