summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Zimuzo Ezeozue <zezeozue@google.com> 2025-01-16 10:51:04 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-01-16 10:51:04 -0800
commit6fa4ac73b590dda50b9258143d87145dcbec8367 (patch)
treeb36241f1c16b6578f220fa24b4e104b15d9e3c50
parentb91a220683061f2bb01eec4734b9395eb1b932c9 (diff)
parentad0b0ed2bbb578adc64d17d89dcd4c9758b88c73 (diff)
Merge "Improve PerfettoTrace API" into main
-rw-r--r--core/java/android/os/PerfettoTrace.java170
-rw-r--r--core/java/android/os/PerfettoTrackEventExtra.java481
-rw-r--r--core/jni/android_os_PerfettoTrace.cpp49
-rw-r--r--core/jni/android_os_PerfettoTrackEventExtra.cpp54
-rw-r--r--core/tests/coretests/src/android/os/PerfettoTraceTest.java226
5 files changed, 627 insertions, 353 deletions
diff --git a/core/java/android/os/PerfettoTrace.java b/core/java/android/os/PerfettoTrace.java
index 164561acac32..e3f251e34b45 100644
--- a/core/java/android/os/PerfettoTrace.java
+++ b/core/java/android/os/PerfettoTrace.java
@@ -22,7 +22,6 @@ import dalvik.annotation.optimization.FastNative;
import libcore.util.NativeAllocationRegistry;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
/**
* Writes trace events to the perfetto trace buffer. These trace events can be
@@ -72,7 +71,7 @@ public final class PerfettoTrace {
* @param name The category name.
*/
public Category(String name) {
- this(name, null, null);
+ this(name, "", "");
}
/**
@@ -82,7 +81,7 @@ public final class PerfettoTrace {
* @param tag An atrace tag name that this category maps to.
*/
public Category(String name, String tag) {
- this(name, tag, null);
+ this(name, tag, "");
}
/**
@@ -155,9 +154,6 @@ public final class PerfettoTrace {
}
}
- @FastNative
- private static native void native_event(int type, long tag, String name, long ptr);
-
@CriticalNative
private static native long native_get_process_track_uuid();
@@ -170,176 +166,98 @@ public final class PerfettoTrace {
/**
* Writes a trace message to indicate a given section of code was invoked.
*
- * @param category The perfetto category pointer.
+ * @param category The perfetto category.
* @param eventName The event name to appear in the trace.
- * @param extra The extra arguments.
*/
- public static void instant(Category category, String eventName, PerfettoTrackEventExtra extra) {
+ public static PerfettoTrackEventExtra.Builder instant(Category category, String eventName) {
if (!category.isEnabled()) {
- return;
+ return PerfettoTrackEventExtra.noOpBuilder();
}
- native_event(PERFETTO_TE_TYPE_INSTANT, category.getPtr(), eventName, extra.getPtr());
- extra.reset();
- }
-
- /**
- * Writes a trace message to indicate a given section of code was invoked.
- *
- * @param category The perfetto category.
- * @param eventName The event name to appear in the trace.
- * @param extraConfig Consumer for the extra arguments.
- */
- public static void instant(Category category, String eventName,
- Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
- PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
- extraConfig.accept(extra);
- instant(category, eventName, extra.build());
- }
-
- /**
- * Writes a trace message to indicate a given section of code was invoked.
- *
- * @param category The perfetto category.
- * @param eventName The event name to appear in the trace.
- */
- public static void instant(Category category, String eventName) {
- instant(category, eventName, PerfettoTrackEventExtra.builder().build());
+ return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_INSTANT, category)
+ .setEventName(eventName);
}
/**
* Writes a trace message to indicate the start of a given section of code.
*
- * @param category The perfetto category pointer.
+ * @param category The perfetto category.
* @param eventName The event name to appear in the trace.
- * @param extra The extra arguments.
*/
- public static void begin(Category category, String eventName, PerfettoTrackEventExtra extra) {
+ public static PerfettoTrackEventExtra.Builder begin(Category category, String eventName) {
if (!category.isEnabled()) {
- return;
+ return PerfettoTrackEventExtra.noOpBuilder();
}
- native_event(PERFETTO_TE_TYPE_SLICE_BEGIN, category.getPtr(), eventName, extra.getPtr());
- extra.reset();
- }
-
- /**
- * Writes a trace message to indicate the start of a given section of code.
- *
- * @param category The perfetto category pointer.
- * @param eventName The event name to appear in the trace.
- * @param extraConfig Consumer for the extra arguments.
- */
- public static void begin(Category category, String eventName,
- Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
- PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
- extraConfig.accept(extra);
- begin(category, eventName, extra.build());
- }
-
- /**
- * Writes a trace message to indicate the start of a given section of code.
- *
- * @param category The perfetto category pointer.
- * @param eventName The event name to appear in the trace.
- */
- public static void begin(Category category, String eventName) {
- begin(category, eventName, PerfettoTrackEventExtra.builder().build());
+ return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_SLICE_BEGIN, category)
+ .setEventName(eventName);
}
/**
* Writes a trace message to indicate the end of a given section of code.
*
- * @param category The perfetto category pointer.
- * @param extra The extra arguments.
+ * @param category The perfetto category.
*/
- public static void end(Category category, PerfettoTrackEventExtra extra) {
+ public static PerfettoTrackEventExtra.Builder end(Category category) {
if (!category.isEnabled()) {
- return;
+ return PerfettoTrackEventExtra.noOpBuilder();
}
- native_event(PERFETTO_TE_TYPE_SLICE_END, category.getPtr(), "", extra.getPtr());
- extra.reset();
- }
-
- /**
- * Writes a trace message to indicate the end of a given section of code.
- *
- * @param category The perfetto category pointer.
- * @param extraConfig Consumer for the extra arguments.
- */
- public static void end(Category category,
- Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
- PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
- extraConfig.accept(extra);
- end(category, extra.build());
- }
-
- /**
- * Writes a trace message to indicate the end of a given section of code.
- *
- * @param category The perfetto category pointer.
- */
- public static void end(Category category) {
- end(category, PerfettoTrackEventExtra.builder().build());
+ return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_SLICE_END, category);
}
/**
* Writes a trace message to indicate the value of a given section of code.
*
- * @param category The perfetto category pointer.
- * @param extra The extra arguments.
+ * @param category The perfetto category.
+ * @param value The value of the counter.
*/
- public static void counter(Category category, PerfettoTrackEventExtra extra) {
+ public static PerfettoTrackEventExtra.Builder counter(Category category, long value) {
if (!category.isEnabled()) {
- return;
+ return PerfettoTrackEventExtra.noOpBuilder();
}
- native_event(PERFETTO_TE_TYPE_COUNTER, category.getPtr(), "", extra.getPtr());
- extra.reset();
+ return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_COUNTER, category)
+ .setCounter(value);
}
/**
* Writes a trace message to indicate the value of a given section of code.
*
- * @param category The perfetto category pointer.
- * @param extraConfig Consumer for the extra arguments.
+ * @param category The perfetto category.
+ * @param value The value of the counter.
+ * @param trackName The trackName for the event.
*/
- public static void counter(Category category,
- Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
- PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
- extraConfig.accept(extra);
- counter(category, extra.build());
+ public static PerfettoTrackEventExtra.Builder counter(
+ Category category, long value, String trackName) {
+ return counter(category, value).usingProcessCounterTrack(trackName);
}
/**
* Writes a trace message to indicate the value of a given section of code.
*
- * @param category The perfetto category pointer.
- * @param trackName The trackName for the event.
+ * @param category The perfetto category.
* @param value The value of the counter.
*/
- public static void counter(Category category, String trackName, long value) {
- PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder()
- .usingCounterTrack(trackName, PerfettoTrace.getProcessTrackUuid())
- .setCounter(value)
- .build();
- counter(category, extra);
+ public static PerfettoTrackEventExtra.Builder counter(Category category, double value) {
+ if (!category.isEnabled()) {
+ return PerfettoTrackEventExtra.noOpBuilder();
+ }
+
+ return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_COUNTER, category)
+ .setCounter(value);
}
/**
* Writes a trace message to indicate the value of a given section of code.
*
- * @param category The perfetto category pointer.
- * @param trackName The trackName for the event.
+ * @param category The perfetto category.
* @param value The value of the counter.
+ * @param trackName The trackName for the event.
*/
- public static void counter(Category category, String trackName, double value) {
- PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder()
- .usingCounterTrack(trackName, PerfettoTrace.getProcessTrackUuid())
- .setCounter(value)
- .build();
- counter(category, extra);
+ public static PerfettoTrackEventExtra.Builder counter(
+ Category category, double value, String trackName) {
+ return counter(category, value).usingProcessCounterTrack(trackName);
}
/**
@@ -360,7 +278,7 @@ public final class PerfettoTrace {
* Returns the process track uuid that can be used as a parent track uuid.
*/
public static long getProcessTrackUuid() {
- if (IS_FLAG_ENABLED) {
+ if (!IS_FLAG_ENABLED) {
return 0;
}
return native_get_process_track_uuid();
@@ -370,7 +288,7 @@ public final class PerfettoTrace {
* Given a thread tid, returns the thread track uuid that can be used as a parent track uuid.
*/
public static long getThreadTrackUuid(long tid) {
- if (IS_FLAG_ENABLED) {
+ if (!IS_FLAG_ENABLED) {
return 0;
}
return native_get_thread_track_uuid(tid);
@@ -380,7 +298,7 @@ public final class PerfettoTrace {
* Activates a trigger by name {@code triggerName} with expiry in {@code ttlMs}.
*/
public static void activateTrigger(String triggerName, int ttlMs) {
- if (IS_FLAG_ENABLED) {
+ if (!IS_FLAG_ENABLED) {
return;
}
native_activate_trigger(triggerName, ttlMs);
diff --git a/core/java/android/os/PerfettoTrackEventExtra.java b/core/java/android/os/PerfettoTrackEventExtra.java
index a219b3b5678b..e034fb3726e3 100644
--- a/core/java/android/os/PerfettoTrackEventExtra.java
+++ b/core/java/android/os/PerfettoTrackEventExtra.java
@@ -31,6 +31,7 @@ import java.util.function.Supplier;
*/
public final class PerfettoTrackEventExtra {
private static final int DEFAULT_EXTRA_CACHE_SIZE = 5;
+ private static final Builder NO_OP_BUILDER = new NoOpBuilder();
private static final ThreadLocal<PerfettoTrackEventExtra> sTrackEventExtra =
new ThreadLocal<PerfettoTrackEventExtra>() {
@Override
@@ -40,7 +41,6 @@ public final class PerfettoTrackEventExtra {
};
private static final AtomicLong sNamedTrackId = new AtomicLong();
- private boolean mIsInUse;
private CounterInt64 mCounterInt64;
private CounterDouble mCounterDouble;
private Proto mProto;
@@ -123,15 +123,299 @@ public final class PerfettoTrackEventExtra {
}
}
+ public interface Builder {
+ /**
+ * Emits the track event.
+ */
+ void emit();
+
+ /**
+ * Initialize the builder for a new trace event.
+ */
+ Builder init(int traceType, PerfettoTrace.Category category);
+
+ /**
+ * Sets the event name for the track event.
+ *
+ * @param eventName can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code eventName} should be the string itself.
+ * @param args format arguments if {@code eventName} is specified.
+ */
+ Builder setEventName(String eventName, Object... args);
+
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ */
+ Builder addArg(String name, long val);
+
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ */
+ Builder addArg(String name, boolean val);
+
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ */
+ Builder addArg(String name, double val);
+
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ *
+ * @param val can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code val} should be the string itself.
+ * @param args format arguments if {@code val} is specified.
+ */
+ Builder addArg(String name, String val, Object... args);
+
+ /**
+ * Adds a flow with {@code id}.
+ */
+ Builder addFlow(int id);
+
+ /**
+ * Adds a terminating flow with {@code id}.
+ */
+ Builder addTerminatingFlow(int id);
+
+ /**
+ * Adds the events to a named track instead of the thread track where the
+ * event occurred.
+ *
+ * @param name can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code name} should be the string itself.
+ * @param args format arguments if {@code name} is specified.
+ */
+ Builder usingNamedTrack(long parentUuid, String name, Object... args);
+
+ /**
+ * Adds the events to a process scoped named track instead of the thread track where the
+ * event occurred.
+ *
+ * @param name can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code name} should be the string itself.
+ * @param args format arguments if {@code name} is specified.
+ */
+ Builder usingProcessNamedTrack(String name, Object... args);
+
+ /**
+ * Adds the events to a thread scoped named track instead of the thread track where the
+ * event occurred.
+ *
+ * @param name can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code name} should be the string itself.
+ * @param args format arguments if {@code name} is specified.
+ */
+ Builder usingThreadNamedTrack(long tid, String name, Object... args);
+
+ /**
+ * Adds the events to a counter track instead. This is required for
+ * setting counter values.
+ *
+ * @param name can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code name} should be the string itself.
+ * @param args format arguments if {@code name} is specified.
+ */
+ Builder usingCounterTrack(long parentUuid, String name, Object... args);
+
+ /**
+ * Adds the events to a process scoped counter track instead. This is required for
+ * setting counter values.
+ *
+ * @param name can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code name} should be the string itself.
+ * @param args format arguments if {@code eventName} is specified.
+ */
+ Builder usingProcessCounterTrack(String name, Object... args);
+
+ /**
+ * Adds the events to a thread scoped counter track instead. This is required for
+ * setting counter values.
+ *
+ * @param name can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code name} should be the string itself.
+ * @param args format arguments if {@code name} is specified.
+ */
+ Builder usingThreadCounterTrack(long tid, String name, Object... args);
+
+ /**
+ * Sets a long counter value on the event.
+ *
+ */
+ Builder setCounter(long val);
+
+ /**
+ * Sets a double counter value on the event.
+ *
+ */
+ Builder setCounter(double val);
+
+ /**
+ * Adds a proto field with field id {@code id} and value {@code val}.
+ */
+ Builder addField(long id, long val);
+
+ /**
+ * Adds a proto field with field id {@code id} and value {@code val}.
+ */
+ Builder addField(long id, double val);
+
+ /**
+ * Adds a proto field with field id {@code id} and value {@code val}.
+ *
+ * @param val can contain a format string specifier, in which case, the
+ * {@code args} are the format arguments. If no {@code args} are provided,
+ * the {@code val} should be the string itself.
+ * @param args format arguments if {@code val} is specified.
+ */
+ Builder addField(long id, String val, Object... args);
+
+ /**
+ * Begins a proto field with field
+ * Fields can be added from this point and there must be a corresponding
+ * {@link endProto}.
+ *
+ * The proto field is a singleton and all proto fields get added inside the
+ * one {@link beginProto} and {@link endProto} within the {@link Builder}.
+ */
+ Builder beginProto();
+
+ /**
+ * Ends a proto field.
+ */
+ Builder endProto();
+
+ /**
+ * Begins a nested proto field with field id {@code id}.
+ * Fields can be added from this point and there must be a corresponding
+ * {@link endNested}.
+ */
+ Builder beginNested(long id);
+
+ /**
+ * Ends a nested proto field.
+ */
+ Builder endNested();
+ }
+
+ public static final class NoOpBuilder implements Builder {
+ @Override
+ public void emit() {}
+ @Override
+ public Builder init(int traceType, PerfettoTrace.Category category) {
+ return this;
+ }
+ @Override
+ public Builder setEventName(String eventName, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder addArg(String name, long val) {
+ return this;
+ }
+ @Override
+ public Builder addArg(String name, boolean val) {
+ return this;
+ }
+ @Override
+ public Builder addArg(String name, double val) {
+ return this;
+ }
+ @Override
+ public Builder addArg(String name, String val, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder addFlow(int id) {
+ return this;
+ }
+ @Override
+ public Builder addTerminatingFlow(int id) {
+ return this;
+ }
+ @Override
+ public Builder usingNamedTrack(long parentUuid, String name, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder usingProcessNamedTrack(String name, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder usingThreadNamedTrack(long tid, String name, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder usingCounterTrack(long parentUuid, String name, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder usingProcessCounterTrack(String name, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder usingThreadCounterTrack(long tid, String name, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder setCounter(long val) {
+ return this;
+ }
+ @Override
+ public Builder setCounter(double val) {
+ return this;
+ }
+ @Override
+ public Builder addField(long id, long val) {
+ return this;
+ }
+ @Override
+ public Builder addField(long id, double val) {
+ return this;
+ }
+ @Override
+ public Builder addField(long id, String val, Object... args) {
+ return this;
+ }
+ @Override
+ public Builder beginProto() {
+ return this;
+ }
+ @Override
+ public Builder endProto() {
+ return this;
+ }
+ @Override
+ public Builder beginNested(long id) {
+ return this;
+ }
+ @Override
+ public Builder endNested() {
+ return this;
+ }
+ }
+
/**
* Builder for Perfetto track event extras.
*/
- public static final class Builder {
+ public static final class BuilderImpl implements Builder {
// For performance reasons, we hold a reference to mExtra as a holder for
// perfetto pointers being added. This way, we avoid an additional list to hold
// the pointers in Java and we can pass them down directly to native code.
private final PerfettoTrackEventExtra mExtra;
+
+ private int mTraceType;
+ private PerfettoTrace.Category mCategory;
+ private String mEventName;
private boolean mIsBuilt;
+
private Builder mParent;
private FieldContainer mCurrentContainer;
@@ -151,16 +435,10 @@ public final class PerfettoTrackEventExtra {
private final Pool<FieldString> mFieldStringCache;
private final Pool<FieldNested> mFieldNestedCache;
private final Pool<Flow> mFlowCache;
- private final Pool<Builder> mBuilderCache;
+ private final Pool<BuilderImpl> mBuilderCache;
- private Builder() {
- this(sTrackEventExtra.get(), null, null);
- }
-
- private Builder(PerfettoTrackEventExtra extra, Builder parent, FieldContainer container) {
- mExtra = extra;
- mParent = parent;
- mCurrentContainer = container;
+ private BuilderImpl() {
+ mExtra = sTrackEventExtra.get();
mNamedTrackCache = mExtra.mNamedTrackCache;
mCounterTrackCache = mExtra.mCounterTrackCache;
@@ -180,25 +458,39 @@ public final class PerfettoTrackEventExtra {
mProto = mExtra.getProto();
}
- /**
- * Builds the track event extra.
- */
- public PerfettoTrackEventExtra build() {
+ @Override
+ public void emit() {
checkParent();
mIsBuilt = true;
+ native_emit(mTraceType, mCategory.getPtr(), mEventName, mExtra.getPtr());
+ // Reset after emitting to free any the extras used to trace the event.
+ mExtra.reset();
+ }
+
+ @Override
+ public Builder init(int traceType, PerfettoTrace.Category category) {
+ mTraceType = traceType;
+ mCategory = category;
+ mEventName = "";
mFieldInt64Cache.reset();
mFieldDoubleCache.reset();
mFieldStringCache.reset();
mFieldNestedCache.reset();
mBuilderCache.reset();
- return mExtra;
+ mExtra.reset();
+ // Reset after on init in case the thread created builders without calling emit
+ return initInternal(this, null);
}
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
+ @Override
+ public Builder setEventName(String eventName, Object... args) {
+ mEventName = toString(eventName, args);
+ return this;
+ }
+
+ @Override
public Builder addArg(String name, long val) {
checkParent();
ArgInt64 arg = mArgInt64Cache.get(name.hashCode());
@@ -211,9 +503,7 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
+ @Override
public Builder addArg(String name, boolean val) {
checkParent();
ArgBool arg = mArgBoolCache.get(name.hashCode());
@@ -226,9 +516,7 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
+ @Override
public Builder addArg(String name, double val) {
checkParent();
ArgDouble arg = mArgDoubleCache.get(name.hashCode());
@@ -241,24 +529,20 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
- public Builder addArg(String name, String val) {
+ @Override
+ public Builder addArg(String name, String val, Object... args) {
checkParent();
ArgString arg = mArgStringCache.get(name.hashCode());
if (arg == null || !arg.getName().equals(name)) {
arg = new ArgString(name);
mArgStringCache.put(name.hashCode(), arg);
}
- arg.setValue(val);
+ arg.setValue(toString(val, args));
mExtra.addPerfettoPointer(arg);
return this;
}
- /**
- * Adds a flow with {@code id}.
- */
+ @Override
public Builder addFlow(int id) {
checkParent();
Flow flow = mFlowCache.get(Flow::new);
@@ -267,9 +551,7 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds a terminating flow with {@code id}.
- */
+ @Override
public Builder addTerminatingFlow(int id) {
checkParent();
Flow flow = mFlowCache.get(Flow::new);
@@ -278,12 +560,11 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds the events to a named track instead of the thread track where the
- * event occurred.
- */
- public Builder usingNamedTrack(String name, long parentUuid) {
+ @Override
+ public Builder usingNamedTrack(long parentUuid, String name, Object... args) {
checkParent();
+ name = toString(name, args);
+
NamedTrack track = mNamedTrackCache.get(name.hashCode());
if (track == null || !track.getName().equals(name)) {
track = new NamedTrack(name, parentUuid);
@@ -293,13 +574,21 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds the events to a counter track instead. This is required for
- * setting counter values.
- *
- */
- public Builder usingCounterTrack(String name, long parentUuid) {
+ @Override
+ public Builder usingProcessNamedTrack(String name, Object... args) {
+ return usingNamedTrack(PerfettoTrace.getProcessTrackUuid(), name, args);
+ }
+
+ @Override
+ public Builder usingThreadNamedTrack(long tid, String name, Object... args) {
+ return usingNamedTrack(PerfettoTrace.getThreadTrackUuid(tid), name, args);
+ }
+
+ @Override
+ public Builder usingCounterTrack(long parentUuid, String name, Object... args) {
checkParent();
+ name = toString(name, args);
+
CounterTrack track = mCounterTrackCache.get(name.hashCode());
if (track == null || !track.getName().equals(name)) {
track = new CounterTrack(name, parentUuid);
@@ -309,10 +598,17 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Sets a long counter value on the event.
- *
- */
+ @Override
+ public Builder usingProcessCounterTrack(String name, Object... args) {
+ return usingCounterTrack(PerfettoTrace.getProcessTrackUuid(), name, args);
+ }
+
+ @Override
+ public Builder usingThreadCounterTrack(long tid, String name, Object... args) {
+ return usingCounterTrack(PerfettoTrace.getThreadTrackUuid(tid), name, args);
+ }
+
+ @Override
public Builder setCounter(long val) {
checkParent();
mCounterInt64.setValue(val);
@@ -320,10 +616,7 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Sets a double counter value on the event.
- *
- */
+ @Override
public Builder setCounter(double val) {
checkParent();
mCounterDouble.setValue(val);
@@ -331,9 +624,7 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds a proto field with field id {@code id} and value {@code val}.
- */
+ @Override
public Builder addField(long id, long val) {
checkContainer();
FieldInt64 field = mFieldInt64Cache.get(FieldInt64::new);
@@ -342,9 +633,7 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds a proto field with field id {@code id} and value {@code val}.
- */
+ @Override
public Builder addField(long id, double val) {
checkContainer();
FieldDouble field = mFieldDoubleCache.get(FieldDouble::new);
@@ -353,35 +642,24 @@ public final class PerfettoTrackEventExtra {
return this;
}
- /**
- * Adds a proto field with field id {@code id} and value {@code val}.
- */
- public Builder addField(long id, String val) {
+ @Override
+ public Builder addField(long id, String val, Object... args) {
checkContainer();
FieldString field = mFieldStringCache.get(FieldString::new);
- field.setValue(id, val);
+ field.setValue(id, toString(val, args));
mCurrentContainer.addField(field);
return this;
}
- /**
- * Begins a proto field with field
- * Fields can be added from this point and there must be a corresponding
- * {@link endProto}.
- *
- * The proto field is a singleton and all proto fields get added inside the
- * one {@link beginProto} and {@link endProto} within the {@link Builder}.
- */
+ @Override
public Builder beginProto() {
checkParent();
mProto.clearFields();
mExtra.addPerfettoPointer(mProto);
- return mBuilderCache.get(Builder::new).init(this, mProto);
+ return mBuilderCache.get(BuilderImpl::new).initInternal(this, mProto);
}
- /**
- * Ends a proto field.
- */
+ @Override
public Builder endProto() {
if (mParent == null || mCurrentContainer == null) {
throw new IllegalStateException("No proto to end");
@@ -389,22 +667,16 @@ public final class PerfettoTrackEventExtra {
return mParent;
}
- /**
- * Begins a nested proto field with field id {@code id}.
- * Fields can be added from this point and there must be a corresponding
- * {@link endNested}.
- */
+ @Override
public Builder beginNested(long id) {
checkContainer();
FieldNested field = mFieldNestedCache.get(FieldNested::new);
field.setId(id);
mCurrentContainer.addField(field);
- return mBuilderCache.get(Builder::new).init(this, field);
+ return mBuilderCache.get(BuilderImpl::new).initInternal(this, field);
}
- /**
- * Ends a nested proto field.
- */
+ @Override
public Builder endNested() {
if (mParent == null || mCurrentContainer == null) {
throw new IllegalStateException("No nested field to end");
@@ -412,21 +684,15 @@ public final class PerfettoTrackEventExtra {
return mParent;
}
- /**
- * Initializes a {@link Builder}.
- */
- public Builder init(Builder parent, FieldContainer container) {
+ private static String toString(String val, Object... args) {
+ return args == null || args.length == 0 ? val : String.format(val, args);
+ }
+
+ private Builder initInternal(Builder parent, FieldContainer container) {
mParent = parent;
mCurrentContainer = container;
mIsBuilt = false;
- if (mParent == null) {
- if (mExtra.mIsInUse) {
- throw new IllegalStateException("Cannot create a new builder when another"
- + " extra is in use");
- }
- mExtra.mIsInUse = true;
- }
return this;
}
@@ -439,9 +705,8 @@ public final class PerfettoTrackEventExtra {
private void checkParent() {
checkState();
- if (mParent != null) {
- throw new IllegalStateException(
- "This builder has already been used. Create a new builder for another event.");
+ if (!this.equals(mParent)) {
+ throw new IllegalStateException("Operation not supported for proto");
}
}
@@ -458,7 +723,14 @@ public final class PerfettoTrackEventExtra {
* Start a {@link Builder} to build a {@link PerfettoTrackEventExtra}.
*/
public static Builder builder() {
- return sTrackEventExtra.get().mBuilderCache.get(Builder::new).init(null, null);
+ return sTrackEventExtra.get().mBuilderCache.get(BuilderImpl::new).initInternal(null, null);
+ }
+
+ /**
+ * Returns a no-op {@link Builder}. Useful if a category is disabled.
+ */
+ public static Builder noOpBuilder() {
+ return NO_OP_BUILDER;
}
private final RingBuffer<NamedTrack> mNamedTrackCache =
@@ -476,7 +748,7 @@ public final class PerfettoTrackEventExtra {
private final Pool<FieldString> mFieldStringCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private final Pool<FieldNested> mFieldNestedCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private final Pool<Flow> mFlowCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
- private final Pool<Builder> mBuilderCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+ private final Pool<BuilderImpl> mBuilderCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
@@ -509,7 +781,6 @@ public final class PerfettoTrackEventExtra {
*/
public void reset() {
native_clear_args(mPtr);
- mIsInUse = false;
}
private CounterInt64 getCounterInt64() {
@@ -1078,4 +1349,6 @@ public final class PerfettoTrackEventExtra {
private static native void native_add_arg(long ptr, long extraPtr);
@CriticalNative
private static native void native_clear_args(long ptr);
+ @FastNative
+ private static native void native_emit(int type, long tag, String name, long ptr);
}
diff --git a/core/jni/android_os_PerfettoTrace.cpp b/core/jni/android_os_PerfettoTrace.cpp
index 988aea722be3..962aefc482e4 100644
--- a/core/jni/android_os_PerfettoTrace.cpp
+++ b/core/jni/android_os_PerfettoTrace.cpp
@@ -23,6 +23,7 @@
#include <nativehelper/scoped_local_ref.h>
#include <nativehelper/scoped_primitive_array.h>
#include <nativehelper/scoped_utf_chars.h>
+#include <nativehelper/utils.h>
#include <tracing_sdk.h>
namespace android {
@@ -36,30 +37,6 @@ inline static jlong toJLong(T* ptr) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
}
-static const char* fromJavaString(JNIEnv* env, jstring jstr) {
- if (!jstr) return "";
- ScopedUtfChars chars(env, jstr);
-
- if (!chars.c_str()) {
- ALOGE("Failed extracting string");
- return "";
- }
-
- return chars.c_str();
-}
-
-static void android_os_PerfettoTrace_event(JNIEnv* env, jclass, jint type, jlong cat_ptr,
- jstring name, jlong extra_ptr) {
- ScopedUtfChars name_utf(env, name);
- if (!name_utf.c_str()) {
- ALOGE("Failed extracting string");
- }
-
- tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(cat_ptr);
- tracing_perfetto::trace_event(type, category->get(), name_utf.c_str(),
- toPointer<tracing_perfetto::Extra>(extra_ptr));
-}
-
static jlong android_os_PerfettoTrace_get_process_track_uuid() {
return tracing_perfetto::get_process_track_uuid();
}
@@ -70,20 +47,18 @@ static jlong android_os_PerfettoTrace_get_thread_track_uuid(jlong tid) {
static void android_os_PerfettoTrace_activate_trigger(JNIEnv* env, jclass, jstring name,
jint ttl_ms) {
- ScopedUtfChars name_utf(env, name);
- if (!name_utf.c_str()) {
- ALOGE("Failed extracting string");
- return;
- }
-
- tracing_perfetto::activate_trigger(name_utf.c_str(), static_cast<uint32_t>(ttl_ms));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN_VOID(env, name);
+ tracing_perfetto::activate_trigger(name_chars.c_str(), static_cast<uint32_t>(ttl_ms));
}
static jlong android_os_PerfettoTraceCategory_init(JNIEnv* env, jclass, jstring name, jstring tag,
jstring severity) {
- return toJLong(new tracing_perfetto::Category(fromJavaString(env, name),
- fromJavaString(env, tag),
- fromJavaString(env, severity)));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
+ ScopedUtfChars tag_chars = GET_UTF_OR_RETURN(env, tag);
+ ScopedUtfChars severity_chars = GET_UTF_OR_RETURN(env, severity);
+
+ return toJLong(new tracing_perfetto::Category(name_chars.c_str(), tag_chars.c_str(),
+ severity_chars.c_str()));
}
static jlong android_os_PerfettoTraceCategory_delete() {
@@ -121,8 +96,7 @@ static const JNINativeMethod gCategoryMethods[] = {
};
static const JNINativeMethod gTraceMethods[] =
- {{"native_event", "(IJLjava/lang/String;J)V", (void*)android_os_PerfettoTrace_event},
- {"native_get_process_track_uuid", "()J",
+ {{"native_get_process_track_uuid", "()J",
(void*)android_os_PerfettoTrace_get_process_track_uuid},
{"native_get_thread_track_uuid", "(J)J",
(void*)android_os_PerfettoTrace_get_thread_track_uuid},
@@ -132,10 +106,11 @@ static const JNINativeMethod gTraceMethods[] =
int register_android_os_PerfettoTrace(JNIEnv* env) {
int res = jniRegisterNativeMethods(env, "android/os/PerfettoTrace", gTraceMethods,
NELEM(gTraceMethods));
+ LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register perfetto native methods.");
res = jniRegisterNativeMethods(env, "android/os/PerfettoTrace$Category", gCategoryMethods,
NELEM(gCategoryMethods));
- LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+ LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register category native methods.");
return 0;
}
diff --git a/core/jni/android_os_PerfettoTrackEventExtra.cpp b/core/jni/android_os_PerfettoTrackEventExtra.cpp
index 9adad7bca940..b8bdc8c29199 100644
--- a/core/jni/android_os_PerfettoTrackEventExtra.cpp
+++ b/core/jni/android_os_PerfettoTrackEventExtra.cpp
@@ -20,6 +20,7 @@
#include <log/log.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/scoped_utf_chars.h>
+#include <nativehelper/utils.h>
#include <tracing_sdk.h>
static constexpr ssize_t kMaxStrLen = 4096;
@@ -34,32 +35,24 @@ inline static jlong toJLong(T* ptr) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
}
-static const char* fromJavaString(JNIEnv* env, jstring jstr) {
- if (!jstr) return "";
- ScopedUtfChars chars(env, jstr);
-
- if (!chars.c_str()) {
- ALOGE("Failed extracting string");
- return "";
- }
-
- return chars.c_str();
-}
-
static jlong android_os_PerfettoTrackEventExtraArgInt64_init(JNIEnv* env, jclass, jstring name) {
- return toJLong(new tracing_perfetto::DebugArg<int64_t>(fromJavaString(env, name)));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
+ return toJLong(new tracing_perfetto::DebugArg<int64_t>(name_chars.c_str()));
}
static jlong android_os_PerfettoTrackEventExtraArgBool_init(JNIEnv* env, jclass, jstring name) {
- return toJLong(new tracing_perfetto::DebugArg<bool>(fromJavaString(env, name)));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
+ return toJLong(new tracing_perfetto::DebugArg<bool>(name_chars.c_str()));
}
static jlong android_os_PerfettoTrackEventExtraArgDouble_init(JNIEnv* env, jclass, jstring name) {
- return toJLong(new tracing_perfetto::DebugArg<double>(fromJavaString(env, name)));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
+ return toJLong(new tracing_perfetto::DebugArg<double>(name_chars.c_str()));
}
static jlong android_os_PerfettoTrackEventExtraArgString_init(JNIEnv* env, jclass, jstring name) {
- return toJLong(new tracing_perfetto::DebugArg<const char*>(fromJavaString(env, name)));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
+ return toJLong(new tracing_perfetto::DebugArg<const char*>(name_chars.c_str()));
}
static jlong android_os_PerfettoTrackEventExtraArgInt64_delete() {
@@ -116,9 +109,11 @@ static void android_os_PerfettoTrackEventExtraArgDouble_set_value(jlong ptr, jdo
static void android_os_PerfettoTrackEventExtraArgString_set_value(JNIEnv* env, jclass, jlong ptr,
jstring val) {
+ ScopedUtfChars val_chars = GET_UTF_OR_RETURN_VOID(env, val);
+
tracing_perfetto::DebugArg<const char*>* arg =
toPointer<tracing_perfetto::DebugArg<const char*>>(ptr);
- arg->set_value(strdup(fromJavaString(env, val)));
+ arg->set_value(strdup(val_chars.c_str()));
}
static jlong android_os_PerfettoTrackEventExtraFieldInt64_init() {
@@ -191,9 +186,11 @@ static void android_os_PerfettoTrackEventExtraFieldDouble_set_value(jlong ptr, j
static void android_os_PerfettoTrackEventExtraFieldString_set_value(JNIEnv* env, jclass, jlong ptr,
jlong id, jstring val) {
+ ScopedUtfChars val_chars = GET_UTF_OR_RETURN_VOID(env, val);
+
tracing_perfetto::ProtoField<const char*>* field =
toPointer<tracing_perfetto::ProtoField<const char*>>(ptr);
- field->set_value(id, strdup(fromJavaString(env, val)));
+ field->set_value(id, strdup(val_chars.c_str()));
}
static void android_os_PerfettoTrackEventExtraFieldNested_add_field(jlong field_ptr,
@@ -234,7 +231,8 @@ static jlong android_os_PerfettoTrackEventExtraFlow_get_extra_ptr(jlong ptr) {
static jlong android_os_PerfettoTrackEventExtraNamedTrack_init(JNIEnv* env, jclass, jlong id,
jstring name, jlong parent_uuid) {
- return toJLong(new tracing_perfetto::NamedTrack(id, parent_uuid, fromJavaString(env, name)));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
+ return toJLong(new tracing_perfetto::NamedTrack(id, parent_uuid, name_chars.c_str()));
}
static jlong android_os_PerfettoTrackEventExtraNamedTrack_delete() {
@@ -248,8 +246,9 @@ static jlong android_os_PerfettoTrackEventExtraNamedTrack_get_extra_ptr(jlong pt
static jlong android_os_PerfettoTrackEventExtraCounterTrack_init(JNIEnv* env, jclass, jstring name,
jlong parent_uuid) {
- return toJLong(
- new tracing_perfetto::RegisteredTrack(1, parent_uuid, fromJavaString(env, name), true));
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
+
+ return toJLong(new tracing_perfetto::RegisteredTrack(1, parent_uuid, name_chars.c_str(), true));
}
static jlong android_os_PerfettoTrackEventExtraCounterTrack_delete() {
@@ -317,6 +316,15 @@ static void android_os_PerfettoTrackEventExtra_clear_args(jlong ptr) {
extra->clear_extras();
}
+static void android_os_PerfettoTrackEventExtra_emit(JNIEnv* env, jclass, jint type, jlong cat_ptr,
+ jstring name, jlong extra_ptr) {
+ ScopedUtfChars name_chars = GET_UTF_OR_RETURN_VOID(env, name);
+
+ tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(cat_ptr);
+ tracing_perfetto::trace_event(type, category->get(), name_chars.c_str(),
+ toPointer<tracing_perfetto::Extra>(extra_ptr));
+}
+
static jlong android_os_PerfettoTrackEventExtraProto_init() {
return toJLong(new tracing_perfetto::Proto());
}
@@ -344,7 +352,9 @@ static const JNINativeMethod gExtraMethods[] =
{{"native_init", "()J", (void*)android_os_PerfettoTrackEventExtra_init},
{"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtra_delete},
{"native_add_arg", "(JJ)V", (void*)android_os_PerfettoTrackEventExtra_add_arg},
- {"native_clear_args", "(J)V", (void*)android_os_PerfettoTrackEventExtra_clear_args}};
+ {"native_clear_args", "(J)V", (void*)android_os_PerfettoTrackEventExtra_clear_args},
+ {"native_emit", "(IJLjava/lang/String;J)V",
+ (void*)android_os_PerfettoTrackEventExtra_emit}};
static const JNINativeMethod gProtoMethods[] =
{{"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraProto_init},
diff --git a/core/tests/coretests/src/android/os/PerfettoTraceTest.java b/core/tests/coretests/src/android/os/PerfettoTraceTest.java
index 292f7500479b..ad28383689af 100644
--- a/core/tests/coretests/src/android/os/PerfettoTraceTest.java
+++ b/core/tests/coretests/src/android/os/PerfettoTraceTest.java
@@ -112,15 +112,14 @@ public class PerfettoTraceTest {
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder()
+ PerfettoTrace.instant(FOO_CATEGORY, "event")
.addFlow(2)
.addTerminatingFlow(3)
.addArg("long_val", 10000000000L)
.addArg("bool_val", true)
.addArg("double_val", 3.14)
.addArg("string_val", FOO)
- .build();
- PerfettoTrace.instant(FOO_CATEGORY, "event", extra);
+ .emit();
byte[] traceBytes = nativeStopTracing(ptr);
@@ -163,12 +162,12 @@ public class PerfettoTraceTest {
@Test
@RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
- public void testDebugAnnotationsWithLamda() throws Exception {
+ public void testDebugAnnotationsWithLambda() throws Exception {
TraceConfig traceConfig = getTraceConfig(FOO);
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrace.instant(FOO_CATEGORY, "event", e -> e.addArg("long_val", 123L));
+ PerfettoTrace.instant(FOO_CATEGORY, "event").addArg("long_val", 123L).emit();
byte[] traceBytes = nativeStopTracing(ptr);
@@ -203,15 +202,14 @@ public class PerfettoTraceTest {
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrackEventExtra beginExtra = PerfettoTrackEventExtra.builder()
- .usingNamedTrack(FOO, PerfettoTrace.getProcessTrackUuid())
- .build();
- PerfettoTrace.begin(FOO_CATEGORY, "event", beginExtra);
+ PerfettoTrace.begin(FOO_CATEGORY, "event")
+ .usingNamedTrack(PerfettoTrace.getProcessTrackUuid(), FOO)
+ .emit();
- PerfettoTrackEventExtra endExtra = PerfettoTrackEventExtra.builder()
- .usingNamedTrack("bar", PerfettoTrace.getThreadTrackUuid(Process.myTid()))
- .build();
- PerfettoTrace.end(FOO_CATEGORY, endExtra);
+
+ PerfettoTrace.end(FOO_CATEGORY)
+ .usingNamedTrack(PerfettoTrace.getThreadTrackUuid(Process.myTid()), "bar")
+ .emit();
Trace trace = Trace.parseFrom(nativeStopTracing(ptr));
@@ -242,26 +240,67 @@ public class PerfettoTraceTest {
assertThat(hasTrackUuid).isTrue();
assertThat(mCategoryNames).contains(FOO);
assertThat(mTrackNames).contains(FOO);
+ assertThat(mTrackNames).contains("bar");
}
@Test
@RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
- public void testCounter() throws Exception {
+ public void testProcessThreadNamedTrack() throws Exception {
TraceConfig traceConfig = getTraceConfig(FOO);
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrackEventExtra intExtra = PerfettoTrackEventExtra.builder()
- .usingCounterTrack(FOO, PerfettoTrace.getProcessTrackUuid())
- .setCounter(16)
- .build();
- PerfettoTrace.counter(FOO_CATEGORY, intExtra);
+ PerfettoTrace.begin(FOO_CATEGORY, "event")
+ .usingProcessNamedTrack(FOO)
+ .emit();
- PerfettoTrackEventExtra doubleExtra = PerfettoTrackEventExtra.builder()
- .usingCounterTrack("bar", PerfettoTrace.getProcessTrackUuid())
- .setCounter(3.14)
- .build();
- PerfettoTrace.counter(FOO_CATEGORY, doubleExtra);
+
+ PerfettoTrace.end(FOO_CATEGORY)
+ .usingThreadNamedTrack(Process.myTid(), "%s-%s", "bar", "stool")
+ .emit();
+
+ Trace trace = Trace.parseFrom(nativeStopTracing(ptr));
+
+ boolean hasTrackEvent = false;
+ boolean hasTrackUuid = false;
+ for (TracePacket packet: trace.getPacketList()) {
+ TrackEvent event;
+ if (packet.hasTrackEvent()) {
+ hasTrackEvent = true;
+ event = packet.getTrackEvent();
+
+ if (TrackEvent.Type.TYPE_SLICE_BEGIN.equals(event.getType())
+ && event.hasTrackUuid()) {
+ hasTrackUuid = true;
+ }
+
+ if (TrackEvent.Type.TYPE_SLICE_END.equals(event.getType())
+ && event.hasTrackUuid()) {
+ hasTrackUuid &= true;
+ }
+ }
+
+ collectInternedData(packet);
+ collectTrackNames(packet);
+ }
+
+ assertThat(hasTrackEvent).isTrue();
+ assertThat(hasTrackUuid).isTrue();
+ assertThat(mCategoryNames).contains(FOO);
+ assertThat(mTrackNames).contains(FOO);
+ assertThat(mTrackNames).contains("bar-stool");
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+ public void testCounterSimple() throws Exception {
+ TraceConfig traceConfig = getTraceConfig(FOO);
+
+ long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+ PerfettoTrace.counter(FOO_CATEGORY, 16, FOO).emit();
+
+ PerfettoTrace.counter(FOO_CATEGORY, 3.14, "bar").emit();
Trace trace = Trace.parseFrom(nativeStopTracing(ptr));
@@ -297,12 +336,102 @@ public class PerfettoTraceTest {
@Test
@RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+ public void testCounter() throws Exception {
+ TraceConfig traceConfig = getTraceConfig(FOO);
+
+ long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+ PerfettoTrace.counter(FOO_CATEGORY, 16)
+ .usingCounterTrack(PerfettoTrace.getProcessTrackUuid(), FOO).emit();
+
+ PerfettoTrace.counter(FOO_CATEGORY, 3.14)
+ .usingCounterTrack(PerfettoTrace.getThreadTrackUuid(Process.myTid()),
+ "%s-%s", "bar", "stool").emit();
+
+ Trace trace = Trace.parseFrom(nativeStopTracing(ptr));
+
+ boolean hasTrackEvent = false;
+ boolean hasCounterValue = false;
+ boolean hasDoubleCounterValue = false;
+ for (TracePacket packet: trace.getPacketList()) {
+ TrackEvent event;
+ if (packet.hasTrackEvent()) {
+ hasTrackEvent = true;
+ event = packet.getTrackEvent();
+
+ if (TrackEvent.Type.TYPE_COUNTER.equals(event.getType())
+ && event.getCounterValue() == 16) {
+ hasCounterValue = true;
+ }
+
+ if (TrackEvent.Type.TYPE_COUNTER.equals(event.getType())
+ && event.getDoubleCounterValue() == 3.14) {
+ hasDoubleCounterValue = true;
+ }
+ }
+
+ collectTrackNames(packet);
+ }
+
+ assertThat(hasTrackEvent).isTrue();
+ assertThat(hasCounterValue).isTrue();
+ assertThat(hasDoubleCounterValue).isTrue();
+ assertThat(mTrackNames).contains(FOO);
+ assertThat(mTrackNames).contains("bar-stool");
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+ public void testProcessThreadCounter() throws Exception {
+ TraceConfig traceConfig = getTraceConfig(FOO);
+
+ long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+ PerfettoTrace.counter(FOO_CATEGORY, 16).usingProcessCounterTrack(FOO).emit();
+
+ PerfettoTrace.counter(FOO_CATEGORY, 3.14)
+ .usingThreadCounterTrack(Process.myTid(), "%s-%s", "bar", "stool").emit();
+
+ Trace trace = Trace.parseFrom(nativeStopTracing(ptr));
+
+ boolean hasTrackEvent = false;
+ boolean hasCounterValue = false;
+ boolean hasDoubleCounterValue = false;
+ for (TracePacket packet: trace.getPacketList()) {
+ TrackEvent event;
+ if (packet.hasTrackEvent()) {
+ hasTrackEvent = true;
+ event = packet.getTrackEvent();
+
+ if (TrackEvent.Type.TYPE_COUNTER.equals(event.getType())
+ && event.getCounterValue() == 16) {
+ hasCounterValue = true;
+ }
+
+ if (TrackEvent.Type.TYPE_COUNTER.equals(event.getType())
+ && event.getDoubleCounterValue() == 3.14) {
+ hasDoubleCounterValue = true;
+ }
+ }
+
+ collectTrackNames(packet);
+ }
+
+ assertThat(hasTrackEvent).isTrue();
+ assertThat(hasCounterValue).isTrue();
+ assertThat(hasDoubleCounterValue).isTrue();
+ assertThat(mTrackNames).contains(FOO);
+ assertThat(mTrackNames).contains("bar-stool");
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
public void testProto() throws Exception {
TraceConfig traceConfig = getTraceConfig(FOO);
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrackEventExtra extra5 = PerfettoTrackEventExtra.builder()
+ PerfettoTrace.instant(FOO_CATEGORY, "event_proto")
.beginProto()
.beginNested(33L)
.addField(4L, 2L)
@@ -310,8 +439,7 @@ public class PerfettoTraceTest {
.endNested()
.addField(2001, "AIDL::IActivityManager")
.endProto()
- .build();
- PerfettoTrace.instant(FOO_CATEGORY, "event_proto", extra5);
+ .emit();
byte[] traceBytes = nativeStopTracing(ptr);
@@ -351,7 +479,7 @@ public class PerfettoTraceTest {
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrackEventExtra extra6 = PerfettoTrackEventExtra.builder()
+ PerfettoTrace.instant(FOO_CATEGORY, "event_proto_nested")
.beginProto()
.beginNested(29L)
.beginNested(4L)
@@ -364,8 +492,7 @@ public class PerfettoTraceTest {
.endNested()
.endNested()
.endProto()
- .build();
- PerfettoTrace.instant(FOO_CATEGORY, "event_proto_nested", extra6);
+ .emit();
byte[] traceBytes = nativeStopTracing(ptr);
@@ -413,8 +540,7 @@ public class PerfettoTraceTest {
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder().build();
- PerfettoTrace.instant(FOO_CATEGORY, "event_trigger", extra);
+ PerfettoTrace.instant(FOO_CATEGORY, "event_trigger").emit();
PerfettoTrace.activateTrigger(FOO, 1000);
@@ -439,49 +565,21 @@ public class PerfettoTraceTest {
@Test
@RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
- public void testMultipleExtras() throws Exception {
- boolean hasException = false;
- try {
- PerfettoTrackEventExtra.builder();
-
- // Unclosed extra will throw an exception here
- PerfettoTrackEventExtra.builder();
- } catch (Exception e) {
- hasException = true;
- }
-
- try {
- PerfettoTrackEventExtra.builder().build();
-
- // Closed extra but unused (reset hasn't been called internally) will throw an exception
- // here.
- PerfettoTrackEventExtra.builder();
- } catch (Exception e) {
- hasException &= true;
- }
-
- assertThat(hasException).isTrue();
- }
-
- @Test
- @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
public void testRegister() throws Exception {
TraceConfig traceConfig = getTraceConfig(BAR);
Category barCategory = new Category(BAR);
long ptr = nativeStartTracing(traceConfig.toByteArray());
- PerfettoTrackEventExtra beforeExtra = PerfettoTrackEventExtra.builder()
+ PerfettoTrace.instant(barCategory, "event")
.addArg("before", 1)
- .build();
- PerfettoTrace.instant(barCategory, "event", beforeExtra);
+ .emit();
barCategory.register();
- PerfettoTrackEventExtra afterExtra = PerfettoTrackEventExtra.builder()
+ PerfettoTrace.instant(barCategory, "event")
.addArg("after", 1)
- .build();
- PerfettoTrace.instant(barCategory, "event", afterExtra);
+ .emit();
byte[] traceBytes = nativeStopTracing(ptr);