Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4854cf3 authored by Pablo Gamito's avatar Pablo Gamito Committed by Android (Google) Code Review
Browse files

Merge changes from topic "update-perfetto-java-side-api-usage" into main

* changes:
  Remove IOException from trace callback function signature
  Update Perfetto API used by Java side
parents 6eef5fc9 93399529
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -71,9 +71,24 @@ public abstract class DataSource<DataSourceInstanceType extends DataSourceInstan
     * @param fun The tracing lambda that will be called with the tracing contexts of each active
     *            tracing instance.
     */
    public final void trace(
            TraceFunction<DataSourceInstanceType, TlsStateType, IncrementalStateType> fun) {
        nativeTrace(mNativeObj, fun);
    public final void trace(TraceFunction<TlsStateType, IncrementalStateType> fun) {
        boolean startedIterator = nativePerfettoDsTraceIterateBegin(mNativeObj);

        if (!startedIterator) {
            return;
        }

        try {
            do {
                TracingContext<TlsStateType, IncrementalStateType> ctx =
                        new TracingContext<>(mNativeObj);
                fun.trace(ctx);

                ctx.flush();
            } while (nativePerfettoDsTraceIterateNext(mNativeObj));
        } finally {
            nativePerfettoDsTraceIterateBreak(mNativeObj);
        }
    }

    /**
@@ -154,8 +169,6 @@ public abstract class DataSource<DataSourceInstanceType extends DataSourceInstan
            long dataSourcePtr, int bufferExhaustedPolicy);

    private static native long nativeCreate(DataSource thiz, String name);
    private static native void nativeTrace(
            long nativeDataSourcePointer, TraceFunction traceFunction);
    private static native void nativeFlushAll(long nativeDataSourcePointer);
    private static native long nativeGetFinalizer();

@@ -163,4 +176,8 @@ public abstract class DataSource<DataSourceInstanceType extends DataSourceInstan
            long dataSourcePtr, int dsInstanceIdx);
    private static native void nativeReleasePerfettoInstanceLocked(
            long dataSourcePtr, int dsInstanceIdx);

    private static native boolean nativePerfettoDsTraceIterateBegin(long dataSourcePtr);
    private static native boolean nativePerfettoDsTraceIterateNext(long dataSourcePtr);
    private static native void nativePerfettoDsTraceIterateBreak(long dataSourcePtr);
}
+2 −7
Original line number Diff line number Diff line
@@ -16,19 +16,15 @@

package android.tracing.perfetto;

import java.io.IOException;

/**
 * The interface for the trace function called from native on a trace call with a context.
 *
 * @param <DataSourceInstanceType> The type of DataSource this tracing context is for.
 * @param <TlsStateType> The type of the custom TLS state, if any is used.
 * @param <IncrementalStateType> The type of the custom incremental state, if any is used.
 *
 * @hide
 */
public interface TraceFunction<DataSourceInstanceType extends DataSourceInstance,
        TlsStateType, IncrementalStateType> {
public interface TraceFunction<TlsStateType, IncrementalStateType> {

    /**
     * This function will be called synchronously (i.e., always before trace() returns) only if
@@ -38,6 +34,5 @@ public interface TraceFunction<DataSourceInstanceType extends DataSourceInstance
     *
     * @param ctx the tracing context to trace for in the trace function.
     */
    void trace(TracingContext<DataSourceInstanceType, TlsStateType, IncrementalStateType> ctx)
            throws IOException;
    void trace(TracingContext<TlsStateType, IncrementalStateType> ctx);
}
+10 −17
Original line number Diff line number Diff line
@@ -24,26 +24,18 @@ import java.util.List;
/**
 * Argument passed to the lambda function passed to Trace().
 *
 * @param <DataSourceInstanceType> The type of the datasource this tracing context is for.
 * @param <TlsStateType> The type of the custom TLS state, if any is used.
 * @param <IncrementalStateType> The type of the custom incremental state, if any is used.
 *
 * @hide
 */
public class TracingContext<DataSourceInstanceType extends DataSourceInstance,
        TlsStateType, IncrementalStateType> {
public class TracingContext<TlsStateType, IncrementalStateType> {

    private final long mContextPtr;
    private final TlsStateType mTlsState;
    private final IncrementalStateType mIncrementalState;
    private final long mNativeDsPtr;
    private final List<ProtoOutputStream> mTracePackets = new ArrayList<>();

    // Should only be created from the native side.
    private TracingContext(long contextPtr, TlsStateType tlsState,
            IncrementalStateType incrementalState) {
        this.mContextPtr = contextPtr;
        this.mTlsState = tlsState;
        this.mIncrementalState = incrementalState;
    TracingContext(long nativeDsPtr) {
        this.mNativeDsPtr = nativeDsPtr;
    }

    /**
@@ -69,7 +61,7 @@ public class TracingContext<DataSourceInstanceType extends DataSourceInstance,
     * Stop timeout expires.
     */
    public void flush() {
        nativeFlush(this, mContextPtr);
        nativeFlush(mNativeDsPtr, getAndClearAllPendingTracePackets());
    }

    /**
@@ -80,7 +72,7 @@ public class TracingContext<DataSourceInstanceType extends DataSourceInstance,
     * @return The TlsState instance for the tracing thread and instance.
     */
    public TlsStateType getCustomTlsState() {
        return this.mTlsState;
        return (TlsStateType) nativeGetCustomTls(mNativeDsPtr);
    }

    /**
@@ -90,10 +82,9 @@ public class TracingContext<DataSourceInstanceType extends DataSourceInstance,
     * @return The current IncrementalState object instance.
     */
    public IncrementalStateType getIncrementalState() {
        return this.mIncrementalState;
        return (IncrementalStateType) nativeGetIncrementalState(mNativeDsPtr);
    }

    // Called from native to get trace packets
    private byte[][] getAndClearAllPendingTracePackets() {
        byte[][] res = new byte[mTracePackets.size()][];
        for (int i = 0; i < mTracePackets.size(); i++) {
@@ -105,5 +96,7 @@ public class TracingContext<DataSourceInstanceType extends DataSourceInstance,
        return res;
    }

    private static native void nativeFlush(TracingContext thiz, long ctxPointer);
    private static native void nativeFlush(long dataSourcePtr, byte[][] packetData);
    private static native Object nativeGetCustomTls(long nativeDsPtr);
    private static native Object nativeGetIncrementalState(long nativeDsPtr);
}
+77 −65
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import android.tracing.perfetto.InitArguments;
import android.tracing.perfetto.Producer;
import android.tracing.perfetto.TracingContext;
import android.util.ArrayMap;
import android.util.Log;
import android.util.LongArray;
import android.util.Slog;
import android.util.proto.ProtoInputStream;
@@ -67,6 +68,7 @@ import com.android.internal.protolog.common.LogLevel;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -166,6 +168,7 @@ public class PerfettoProtoLogImpl implements IProtoLog {
        }

        mDataSource.trace(ctx -> {
            try {
                final ProtoOutputStream os = ctx.newTracePacket();

                os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
@@ -173,35 +176,27 @@ public class PerfettoProtoLogImpl implements IProtoLog {
                final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
                while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                    if (pis.getFieldNumber() == (int) MESSAGES) {
                    final long inMessageToken = pis.start(MESSAGES);
                    final long outMessagesToken = os.start(MESSAGES);
                        writeViewerConfigMessage(pis, os);
                    }

                    while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                        switch (pis.getFieldNumber()) {
                            case (int) MessageData.MESSAGE_ID:
                                os.write(MessageData.MESSAGE_ID,
                                        pis.readLong(MessageData.MESSAGE_ID));
                                break;
                            case (int) MESSAGE:
                                os.write(MESSAGE, pis.readString(MESSAGE));
                                break;
                            case (int) LEVEL:
                                os.write(LEVEL, pis.readInt(LEVEL));
                                break;
                            case (int) GROUP_ID:
                                os.write(GROUP_ID, pis.readInt(GROUP_ID));
                                break;
                            default:
                                throw new RuntimeException(
                                        "Unexpected field id " + pis.getFieldNumber());
                    if (pis.getFieldNumber() == (int) GROUPS) {
                        writeViewerConfigGroup(pis, os);
                    }
                }

                    pis.end(inMessageToken);
                    os.end(outMessagesToken);
                os.end(outProtologViewerConfigToken);

                ctx.flush();
            } catch (IOException e) {
                Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump on tracing end", e);
            }
        });

        mDataSource.flush();
    }

                if (pis.getFieldNumber() == (int) GROUPS) {
    private static void writeViewerConfigGroup(
            ProtoInputStream pis, ProtoOutputStream os) throws IOException {
        final long inGroupToken = pis.start(GROUPS);
        final long outGroupToken = os.start(GROUPS);

@@ -228,14 +223,35 @@ public class PerfettoProtoLogImpl implements IProtoLog {
        pis.end(inGroupToken);
        os.end(outGroupToken);
    }
            }

            os.end(outProtologViewerConfigToken);
    private static void writeViewerConfigMessage(
            ProtoInputStream pis, ProtoOutputStream os) throws IOException {
        final long inMessageToken = pis.start(MESSAGES);
        final long outMessagesToken = os.start(MESSAGES);

            ctx.flush();
        });
        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            switch (pis.getFieldNumber()) {
                case (int) MessageData.MESSAGE_ID:
                    os.write(MessageData.MESSAGE_ID,
                            pis.readLong(MessageData.MESSAGE_ID));
                    break;
                case (int) MESSAGE:
                    os.write(MESSAGE, pis.readString(MESSAGE));
                    break;
                case (int) LEVEL:
                    os.write(LEVEL, pis.readInt(LEVEL));
                    break;
                case (int) GROUP_ID:
                    os.write(GROUP_ID, pis.readInt(GROUP_ID));
                    break;
                default:
                    throw new RuntimeException(
                            "Unexpected field id " + pis.getFieldNumber());
            }
        }

        mDataSource.flush();
        pis.end(inMessageToken);
        os.end(outMessagesToken);
    }

    private void logToLogcat(String tag, LogLevel level, long messageHash,
@@ -423,7 +439,7 @@ public class PerfettoProtoLogImpl implements IProtoLog {
        return sw.toString();
    }

    private int internStacktraceString(TracingContext<ProtoLogDataSource.Instance,
    private int internStacktraceString(TracingContext<
            ProtoLogDataSource.TlsState,
            ProtoLogDataSource.IncrementalState> ctx,
            String stacktrace) {
@@ -433,9 +449,7 @@ public class PerfettoProtoLogImpl implements IProtoLog {
    }

    private int internStringArg(
            TracingContext<ProtoLogDataSource.Instance,
            ProtoLogDataSource.TlsState,
            ProtoLogDataSource.IncrementalState> ctx,
            TracingContext<ProtoLogDataSource.TlsState, ProtoLogDataSource.IncrementalState> ctx,
            String string
    ) {
        final ProtoLogDataSource.IncrementalState incrementalState = ctx.getIncrementalState();
@@ -444,9 +458,7 @@ public class PerfettoProtoLogImpl implements IProtoLog {
    }

    private int internString(
            TracingContext<ProtoLogDataSource.Instance,
                ProtoLogDataSource.TlsState,
                ProtoLogDataSource.IncrementalState> ctx,
            TracingContext<ProtoLogDataSource.TlsState, ProtoLogDataSource.IncrementalState> ctx,
            Map<String, Integer> internMap,
            long fieldId,
            String string
+116 −86
Original line number Diff line number Diff line
@@ -42,12 +42,6 @@ static struct {
    jmethodID createIncrementalState;
} gPerfettoDataSourceClassInfo;

static struct {
    jclass clazz;
    jmethodID init;
    jmethodID getAndClearAllPendingTracePackets;
} gTracingContextClassInfo;

static struct {
    jclass clazz;
    jmethodID init;
@@ -68,32 +62,10 @@ struct IncrementalState {
    jobject jobj;
};

static void traceAllPendingPackets(JNIEnv* env, jobject jCtx, PerfettoDsTracerIterator* ctx) {
    jobjectArray packets =
            (jobjectArray)env
                    ->CallObjectMethod(jCtx,
                                       gTracingContextClassInfo.getAndClearAllPendingTracePackets);
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        env->ExceptionClear();

        LOG_ALWAYS_FATAL("Failed to call java context finalize method");
    }

    int packets_count = env->GetArrayLength(packets);
    for (int i = 0; i < packets_count; i++) {
        jbyteArray packet_proto_buffer = (jbyteArray)env->GetObjectArrayElement(packets, i);

        jbyte* raw_proto_buffer = env->GetByteArrayElements(packet_proto_buffer, 0);
        int buffer_size = env->GetArrayLength(packet_proto_buffer);

        struct PerfettoDsRootTracePacket trace_packet;
        PerfettoDsTracerPacketBegin(ctx, &trace_packet);
        PerfettoPbMsgAppendBytes(&trace_packet.msg.msg, (const uint8_t*)raw_proto_buffer,
                                 buffer_size);
        PerfettoDsTracerPacketEnd(ctx, &trace_packet);
    }
}
// In a single thread there can be only one trace point active across all data source, so we can use
// a single global thread_local variable to keep track of the active tracer iterator.
thread_local static bool gInIteration;
thread_local static struct PerfettoDsTracerIterator gIterator;

PerfettoDataSource::PerfettoDataSource(JNIEnv* env, jobject javaDataSource,
                                       std::string dataSourceName)
@@ -164,44 +136,89 @@ jobject PerfettoDataSource::createIncrementalStateGlobalRef(JNIEnv* env,
    return env->NewGlobalRef(incrementalState.get());
}

void PerfettoDataSource::trace(JNIEnv* env, jobject traceFunction) {
    PERFETTO_DS_TRACE(dataSource, ctx) {
        ALOG(LOG_DEBUG, LOG_TAG, "\tin native trace callback function %p", this);
        TlsState* tls_state =
                reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &ctx));
        IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
                PerfettoDsGetIncrementalState(&dataSource, &ctx));
bool PerfettoDataSource::TraceIterateBegin() {
    if (gInIteration) {
        return false;
    }

        ALOG(LOG_DEBUG, LOG_TAG, "\t tls_state = %p", tls_state);
        ALOG(LOG_DEBUG, LOG_TAG, "\t incr_state = %p", incr_state);
    gIterator = PerfettoDsTraceIterateBegin(&dataSource);

    if (gIterator.impl.tracer == nullptr) {
        return false;
    }

        ALOG(LOG_DEBUG, LOG_TAG, "\t tls_state->jobj = %p", tls_state->jobj);
        ALOG(LOG_DEBUG, LOG_TAG, "\t incr_state->jobj = %p", incr_state->jobj);
    gInIteration = true;
    return true;
}

        ScopedLocalRef<jobject> jCtx(env,
                                     env->NewObject(gTracingContextClassInfo.clazz,
                                                    gTracingContextClassInfo.init, &ctx,
                                                    tls_state->jobj, incr_state->jobj));
bool PerfettoDataSource::TraceIterateNext() {
    if (!gInIteration) {
        LOG_ALWAYS_FATAL("Tried calling TraceIterateNext outside of a tracer iteration.");
        return false;
    }

        ALOG(LOG_DEBUG, LOG_TAG, "\t jCtx = %p", jCtx.get());
    PerfettoDsTraceIterateNext(&dataSource, &gIterator);

        jclass objclass = env->GetObjectClass(traceFunction);
        jmethodID method =
                env->GetMethodID(objclass, "trace", "(Landroid/tracing/perfetto/TracingContext;)V");
        if (method == 0) {
            LOG_ALWAYS_FATAL("Failed to get method id");
    if (gIterator.impl.tracer == nullptr) {
        // Reached end of iterator. No more datasource instances.
        gInIteration = false;
        return false;
    }

        env->ExceptionClear();
    return true;
}

        env->CallVoidMethod(traceFunction, method, jCtx.get());
        if (env->ExceptionOccurred()) {
            env->ExceptionDescribe();
            env->ExceptionClear();
            LOG_ALWAYS_FATAL("Failed to call java trace method");
void PerfettoDataSource::TraceIterateBreak() {
    if (!gInIteration) {
        return;
    }

        traceAllPendingPackets(env, jCtx.get(), &ctx);
    PerfettoDsTraceIterateBreak(&dataSource, &gIterator);
    gInIteration = false;
}

jobject PerfettoDataSource::GetCustomTls() {
    if (!gInIteration) {
        LOG_ALWAYS_FATAL("Tried getting CustomTls outside of a tracer iteration.");
        return nullptr;
    }

    TlsState* tls_state =
            reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &gIterator));

    return tls_state->jobj;
}

jobject PerfettoDataSource::GetIncrementalState() {
    if (!gInIteration) {
        LOG_ALWAYS_FATAL("Tried getting IncrementalState outside of a tracer iteration.");
        return nullptr;
    }

    IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
            PerfettoDsGetIncrementalState(&dataSource, &gIterator));

    return incr_state->jobj;
}

void PerfettoDataSource::WritePackets(JNIEnv* env, jobjectArray packets) {
    if (!gInIteration) {
        LOG_ALWAYS_FATAL("Tried writing packets outside of a tracer iteration.");
        return;
    }

    int packets_count = env->GetArrayLength(packets);
    for (int i = 0; i < packets_count; i++) {
        jbyteArray packet_proto_buffer = (jbyteArray)env->GetObjectArrayElement(packets, i);

        jbyte* raw_proto_buffer = env->GetByteArrayElements(packet_proto_buffer, 0);
        int buffer_size = env->GetArrayLength(packet_proto_buffer);

        struct PerfettoDsRootTracePacket trace_packet;
        PerfettoDsTracerPacketBegin(&gIterator, &trace_packet);
        PerfettoPbMsgAppendBytes(&trace_packet.msg.msg, (const uint8_t*)raw_proto_buffer,
                                 buffer_size);
        PerfettoDsTracerPacketEnd(&gIterator, &trace_packet);
    }
}

@@ -229,7 +246,7 @@ jlong nativeCreate(JNIEnv* env, jclass clazz, jobject javaDataSource, jstring na
}

void nativeDestroy(void* ptr) {
    ALOG(LOG_DEBUG, LOG_TAG, "nativeCreate(%p)", ptr);
    ALOG(LOG_DEBUG, LOG_TAG, "nativeDestroy(%p)", ptr);
    PerfettoDataSource* dataSource = reinterpret_cast<PerfettoDataSource*>(ptr);
    dataSource->decStrong((void*)nativeCreate);
}
@@ -239,18 +256,10 @@ static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&nativeDestroy));
}

void nativeTrace(JNIEnv* env, jclass clazz, jlong dataSourcePtr, jobject traceFunctionInterface) {
    ALOG(LOG_DEBUG, LOG_TAG, "nativeTrace(%p)", (void*)dataSourcePtr);
    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);

    datasource->trace(env, traceFunctionInterface);
}

void nativeFlush(JNIEnv* env, jclass clazz, jobject jCtx, jlong ctxPtr) {
    ALOG(LOG_DEBUG, LOG_TAG, "nativeFlush(%p, %p)", jCtx, (void*)ctxPtr);
    auto* ctx = reinterpret_cast<struct PerfettoDsTracerIterator*>(ctxPtr);
    traceAllPendingPackets(env, jCtx, ctx);
    PerfettoDsTracerFlush(ctx, nullptr, nullptr);
void nativeFlush(JNIEnv* env, jclass clazz, jlong ds_ptr, jobjectArray packets) {
    ALOG(LOG_DEBUG, LOG_TAG, "nativeFlush(%p)", (void*)ds_ptr);
    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(ds_ptr);
    datasource->WritePackets(env, packets);
}

void nativeFlushAll(JNIEnv* env, jclass clazz, jlong ptr) {
@@ -414,11 +423,35 @@ void nativeReleasePerfettoInstanceLocked(JNIEnv* env, jclass clazz, jlong dataSo
    PerfettoDsImplReleaseInstanceLocked(datasource->dataSource.impl, instance_idx);
}

bool nativePerfettoDsTraceIterateBegin(JNIEnv* env, jclass clazz, jlong dataSourcePtr) {
    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
    return datasource->TraceIterateBegin();
}

bool nativePerfettoDsTraceIterateNext(JNIEnv* env, jclass clazz, jlong dataSourcePtr) {
    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
    return datasource->TraceIterateNext();
}

void nativePerfettoDsTraceIterateBreak(JNIEnv* env, jclass clazz, jlong dataSourcePtr) {
    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
    return datasource->TraceIterateBreak();
}

jobject nativeGetCustomTls(JNIEnv* env, jclass clazz, jlong dataSourcePtr) {
    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
    return datasource->GetCustomTls();
}

jobject nativeGetIncrementalState(JNIEnv* env, jclass clazz, jlong dataSourcePtr) {
    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
    return datasource->GetIncrementalState();
}

const JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        {"nativeCreate", "(Landroid/tracing/perfetto/DataSource;Ljava/lang/String;)J",
         (void*)nativeCreate},
        {"nativeTrace", "(JLandroid/tracing/perfetto/TraceFunction;)V", (void*)nativeTrace},
        {"nativeFlushAll", "(J)V", (void*)nativeFlushAll},
        {"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer},
        {"nativeRegisterDataSource", "(JI)V", (void*)nativeRegisterDataSource},
@@ -426,11 +459,16 @@ const JNINativeMethod gMethods[] = {
         (void*)nativeGetPerfettoInstanceLocked},
        {"nativeReleasePerfettoInstanceLocked", "(JI)V",
         (void*)nativeReleasePerfettoInstanceLocked},
};

        {"nativePerfettoDsTraceIterateBegin", "(J)Z", (void*)nativePerfettoDsTraceIterateBegin},
        {"nativePerfettoDsTraceIterateNext", "(J)Z", (void*)nativePerfettoDsTraceIterateNext},
        {"nativePerfettoDsTraceIterateBreak", "(J)V", (void*)nativePerfettoDsTraceIterateBreak}};

const JNINativeMethod gMethodsTracingContext[] = {
        /* name, signature, funcPtr */
        {"nativeFlush", "(Landroid/tracing/perfetto/TracingContext;J)V", (void*)nativeFlush},
        {"nativeFlush", "(J[[B)V", (void*)nativeFlush},
        {"nativeGetCustomTls", "(J)Ljava/lang/Object;", (void*)nativeGetCustomTls},
        {"nativeGetIncrementalState", "(J)Ljava/lang/Object;", (void*)nativeGetIncrementalState},
};

int register_android_tracing_PerfettoDataSource(JNIEnv* env) {
@@ -461,14 +499,6 @@ int register_android_tracing_PerfettoDataSource(JNIEnv* env) {
                             "(Landroid/tracing/perfetto/CreateIncrementalStateArgs;)Ljava/lang/"
                             "Object;");

    clazz = env->FindClass("android/tracing/perfetto/TracingContext");
    gTracingContextClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    gTracingContextClassInfo.init = env->GetMethodID(gTracingContextClassInfo.clazz, "<init>",
                                                     "(JLjava/lang/Object;Ljava/lang/Object;)V");
    gTracingContextClassInfo.getAndClearAllPendingTracePackets =
            env->GetMethodID(gTracingContextClassInfo.clazz, "getAndClearAllPendingTracePackets",
                             "()[[B");

    clazz = env->FindClass("android/tracing/perfetto/CreateTlsStateArgs");
    gCreateTlsStateArgsClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    gCreateTlsStateArgsClassInfo.init =
Loading