diff options
6 files changed, 162 insertions, 120 deletions
diff --git a/core/java/android/tracing/perfetto/DataSource.java b/core/java/android/tracing/perfetto/DataSource.java index d0c719b86ac9..46c5685e95a6 100644 --- a/core/java/android/tracing/perfetto/DataSource.java +++ b/core/java/android/tracing/perfetto/DataSource.java @@ -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); } diff --git a/core/java/android/tracing/perfetto/TraceFunction.java b/core/java/android/tracing/perfetto/TraceFunction.java index 62941df70a48..ad84077340ac 100644 --- a/core/java/android/tracing/perfetto/TraceFunction.java +++ b/core/java/android/tracing/perfetto/TraceFunction.java @@ -21,14 +21,12 @@ 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 +36,6 @@ 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) + void trace(TracingContext<TlsStateType, IncrementalStateType> ctx) throws IOException; } diff --git a/core/java/android/tracing/perfetto/TracingContext.java b/core/java/android/tracing/perfetto/TracingContext.java index c1a61a7c2c34..060f9649bb06 100644 --- a/core/java/android/tracing/perfetto/TracingContext.java +++ b/core/java/android/tracing/perfetto/TracingContext.java @@ -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); } diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java index 9f3ce8163bf3..e641155c2316 100644 --- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java @@ -423,7 +423,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 +433,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 +442,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 diff --git a/core/jni/android_tracing_PerfettoDataSource.cpp b/core/jni/android_tracing_PerfettoDataSource.cpp index 25ff853ae7e4..6e1e9eee75a7 100644 --- a/core/jni/android_tracing_PerfettoDataSource.cpp +++ b/core/jni/android_tracing_PerfettoDataSource.cpp @@ -45,12 +45,6 @@ static struct { static struct { jclass clazz; jmethodID init; - jmethodID getAndClearAllPendingTracePackets; -} gTracingContextClassInfo; - -static struct { - jclass clazz; - jmethodID init; } gCreateTlsStateArgsClassInfo; static struct { @@ -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; + } + + gIterator = PerfettoDsTraceIterateBegin(&dataSource); + + if (gIterator.impl.tracer == nullptr) { + return false; + } - ALOG(LOG_DEBUG, LOG_TAG, "\t tls_state = %p", tls_state); - ALOG(LOG_DEBUG, LOG_TAG, "\t incr_state = %p", incr_state); + gInIteration = true; + return true; +} - 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); +bool PerfettoDataSource::TraceIterateNext() { + if (!gInIteration) { + LOG_ALWAYS_FATAL("Tried calling TraceIterateNext outside of a tracer iteration."); + return false; + } - ScopedLocalRef<jobject> jCtx(env, - env->NewObject(gTracingContextClassInfo.clazz, - gTracingContextClassInfo.init, &ctx, - tls_state->jobj, incr_state->jobj)); + PerfettoDsTraceIterateNext(&dataSource, &gIterator); - ALOG(LOG_DEBUG, LOG_TAG, "\t jCtx = %p", jCtx.get()); + if (gIterator.impl.tracer == nullptr) { + // Reached end of iterator. No more datasource instances. + gInIteration = false; + return false; + } - 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"); - } + return true; +} - env->ExceptionClear(); +void PerfettoDataSource::TraceIterateBreak() { + if (!gInIteration) { + return; + } + + 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; +} - env->CallVoidMethod(traceFunction, method, jCtx.get()); - if (env->ExceptionOccurred()) { - env->ExceptionDescribe(); - env->ExceptionClear(); - LOG_ALWAYS_FATAL("Failed to call java trace method"); - } +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); - traceAllPendingPackets(env, jCtx.get(), &ctx); + 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 = diff --git a/core/jni/android_tracing_PerfettoDataSource.h b/core/jni/android_tracing_PerfettoDataSource.h index 906d9f515a2b..209de29f17d6 100644 --- a/core/jni/android_tracing_PerfettoDataSource.h +++ b/core/jni/android_tracing_PerfettoDataSource.h @@ -46,7 +46,15 @@ public: jobject createTlsStateGlobalRef(JNIEnv* env, PerfettoDsInstanceIndex inst_id); jobject createIncrementalStateGlobalRef(JNIEnv* env, PerfettoDsInstanceIndex inst_id); - void trace(JNIEnv* env, jobject trace_function); + + bool TraceIterateBegin(); + bool TraceIterateNext(); + void TraceIterateBreak(); + void WritePackets(JNIEnv* env, jobjectArray packets); + + jobject GetCustomTls(); + jobject GetIncrementalState(); + void flushAll(); private: |