diff options
| author | 2025-01-16 10:51:04 -0800 | |
|---|---|---|
| committer | 2025-01-16 10:51:04 -0800 | |
| commit | 6fa4ac73b590dda50b9258143d87145dcbec8367 (patch) | |
| tree | b36241f1c16b6578f220fa24b4e104b15d9e3c50 | |
| parent | b91a220683061f2bb01eec4734b9395eb1b932c9 (diff) | |
| parent | ad0b0ed2bbb578adc64d17d89dcd4c9758b88c73 (diff) | |
Merge "Improve PerfettoTrace API" into main
| -rw-r--r-- | core/java/android/os/PerfettoTrace.java | 170 | ||||
| -rw-r--r-- | core/java/android/os/PerfettoTrackEventExtra.java | 481 | ||||
| -rw-r--r-- | core/jni/android_os_PerfettoTrace.cpp | 49 | ||||
| -rw-r--r-- | core/jni/android_os_PerfettoTrackEventExtra.cpp | 54 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/os/PerfettoTraceTest.java | 226 |
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); |