• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright 2023 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #define LOG_TAG "NativeJavaPerfettoDs"
18  
19  #include "android_tracing_PerfettoDataSource.h"
20  
21  #include <android_runtime/AndroidRuntime.h>
22  #include <android_runtime/Log.h>
23  #include <nativehelper/JNIHelp.h>
24  #include <perfetto/public/data_source.h>
25  #include <perfetto/public/producer.h>
26  #include <perfetto/public/protos/trace/test_event.pzc.h>
27  #include <perfetto/public/protos/trace/trace_packet.pzc.h>
28  #include <utils/Log.h>
29  #include <utils/RefBase.h>
30  
31  #include <sstream>
32  #include <thread>
33  
34  #include "core_jni_helpers.h"
35  
36  namespace android {
37  
38  static struct {
39      jclass clazz;
40      jmethodID createInstance;
41      jmethodID createTlsState;
42      jmethodID createIncrementalState;
43  } gPerfettoDataSourceClassInfo;
44  
45  static struct {
46      jclass clazz;
47      jmethodID init;
48  } gCreateTlsStateArgsClassInfo;
49  
50  static struct {
51      jclass clazz;
52      jmethodID init;
53  } gCreateIncrementalStateArgsClassInfo;
54  
55  static JavaVM* gVm;
56  
57  struct TlsState {
58      jobject jobj;
59  };
60  
61  struct IncrementalState {
62      jobject jobj;
63  };
64  
65  // In a single thread there can be only one trace point active across all data source, so we can use
66  // a single global thread_local variable to keep track of the active tracer iterator.
67  thread_local static bool gInIteration;
68  thread_local static struct PerfettoDsTracerIterator gIterator;
69  
PerfettoDataSource(JNIEnv * env,jobject javaDataSource,std::string dataSourceName)70  PerfettoDataSource::PerfettoDataSource(JNIEnv* env, jobject javaDataSource,
71                                         std::string dataSourceName)
72        : dataSourceName(std::move(dataSourceName)),
73          mJavaDataSource(env->NewGlobalRef(javaDataSource)) {}
74  
newInstance(JNIEnv * env,void * ds_config,size_t ds_config_size,PerfettoDsInstanceIndex inst_id)75  jobject PerfettoDataSource::newInstance(JNIEnv* env, void* ds_config, size_t ds_config_size,
76                                          PerfettoDsInstanceIndex inst_id) {
77      jbyteArray configArray = env->NewByteArray(ds_config_size);
78  
79      void* temp = env->GetPrimitiveArrayCritical((jarray)configArray, 0);
80      memcpy(temp, ds_config, ds_config_size);
81      env->ReleasePrimitiveArrayCritical(configArray, temp, 0);
82  
83      jobject instance =
84              env->CallObjectMethod(mJavaDataSource, gPerfettoDataSourceClassInfo.createInstance,
85                                    configArray, inst_id);
86  
87      if (env->ExceptionCheck()) {
88          LOGE_EX(env);
89          env->ExceptionClear();
90          LOG_ALWAYS_FATAL("Failed to create new Java Perfetto datasource instance");
91      }
92  
93      return instance;
94  }
95  
TraceIterateBegin()96  bool PerfettoDataSource::TraceIterateBegin() {
97      if (gInIteration) {
98          return false;
99      }
100  
101      gIterator = PerfettoDsTraceIterateBegin(&dataSource);
102  
103      if (gIterator.impl.tracer == nullptr) {
104          return false;
105      }
106  
107      gInIteration = true;
108      return true;
109  }
110  
TraceIterateNext()111  bool PerfettoDataSource::TraceIterateNext() {
112      if (!gInIteration) {
113          LOG_ALWAYS_FATAL("Tried calling TraceIterateNext outside of a tracer iteration.");
114          return false;
115      }
116  
117      PerfettoDsTraceIterateNext(&dataSource, &gIterator);
118  
119      if (gIterator.impl.tracer == nullptr) {
120          // Reached end of iterator. No more datasource instances.
121          gInIteration = false;
122          return false;
123      }
124  
125      return true;
126  }
127  
TraceIterateBreak()128  void PerfettoDataSource::TraceIterateBreak() {
129      if (!gInIteration) {
130          return;
131      }
132  
133      PerfettoDsTraceIterateBreak(&dataSource, &gIterator);
134      gInIteration = false;
135  }
136  
GetInstanceIndex()137  PerfettoDsInstanceIndex PerfettoDataSource::GetInstanceIndex() {
138      if (!gInIteration) {
139          LOG_ALWAYS_FATAL("Tried calling GetInstanceIndex outside of a tracer iteration.");
140          return -1;
141      }
142  
143      return gIterator.impl.inst_id;
144  }
145  
GetCustomTls()146  jobject PerfettoDataSource::GetCustomTls() {
147      if (!gInIteration) {
148          LOG_ALWAYS_FATAL("Tried getting CustomTls outside of a tracer iteration.");
149          return nullptr;
150      }
151  
152      TlsState* tls_state =
153              reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &gIterator));
154  
155      return tls_state->jobj;
156  }
157  
SetCustomTls(jobject tlsState)158  void PerfettoDataSource::SetCustomTls(jobject tlsState) {
159      if (!gInIteration) {
160          LOG_ALWAYS_FATAL("Tried getting CustomTls outside of a tracer iteration.");
161          return;
162      }
163  
164      TlsState* tls_state =
165              reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &gIterator));
166  
167      tls_state->jobj = tlsState;
168  }
169  
GetIncrementalState()170  jobject PerfettoDataSource::GetIncrementalState() {
171      if (!gInIteration) {
172          LOG_ALWAYS_FATAL("Tried getting IncrementalState outside of a tracer iteration.");
173          return nullptr;
174      }
175  
176      IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
177              PerfettoDsGetIncrementalState(&dataSource, &gIterator));
178  
179      return incr_state->jobj;
180  }
181  
SetIncrementalState(jobject incrementalState)182  void PerfettoDataSource::SetIncrementalState(jobject incrementalState) {
183      if (!gInIteration) {
184          LOG_ALWAYS_FATAL("Tried getting IncrementalState outside of a tracer iteration.");
185          return;
186      }
187  
188      IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
189              PerfettoDsGetIncrementalState(&dataSource, &gIterator));
190  
191      incr_state->jobj = incrementalState;
192  }
193  
WritePackets(JNIEnv * env,jobjectArray packets)194  void PerfettoDataSource::WritePackets(JNIEnv* env, jobjectArray packets) {
195      if (!gInIteration) {
196          LOG_ALWAYS_FATAL("Tried writing packets outside of a tracer iteration.");
197          return;
198      }
199  
200      int packets_count = env->GetArrayLength(packets);
201      for (int i = 0; i < packets_count; i++) {
202          jbyteArray packet_proto_buffer = (jbyteArray)env->GetObjectArrayElement(packets, i);
203  
204          jbyte* raw_proto_buffer = env->GetByteArrayElements(packet_proto_buffer, nullptr);
205          int buffer_size = env->GetArrayLength(packet_proto_buffer);
206  
207          struct PerfettoDsRootTracePacket trace_packet;
208          PerfettoDsTracerPacketBegin(&gIterator, &trace_packet);
209          PerfettoPbMsgAppendBytes(&trace_packet.msg.msg, (const uint8_t*)raw_proto_buffer,
210                                   buffer_size);
211          PerfettoDsTracerPacketEnd(&gIterator, &trace_packet);
212  
213          env->ReleaseByteArrayElements(packet_proto_buffer, raw_proto_buffer, 0 /* default mode */);
214      }
215  }
216  
flushAll()217  void PerfettoDataSource::flushAll() {
218      PERFETTO_DS_TRACE(dataSource, ctx) {
219          PerfettoDsTracerFlush(&ctx, nullptr, nullptr);
220      }
221  }
222  
~PerfettoDataSource()223  PerfettoDataSource::~PerfettoDataSource() {
224      JNIEnv* env = AndroidRuntime::getJNIEnv();
225      env->DeleteGlobalRef(mJavaDataSource);
226  }
227  
nativeCreate(JNIEnv * env,jclass clazz,jobject javaDataSource,jstring name)228  jlong nativeCreate(JNIEnv* env, jclass clazz, jobject javaDataSource, jstring name) {
229      const char* nativeString = env->GetStringUTFChars(name, 0);
230      PerfettoDataSource* dataSource = new PerfettoDataSource(env, javaDataSource, nativeString);
231      env->ReleaseStringUTFChars(name, nativeString);
232  
233      dataSource->incStrong((void*)nativeCreate);
234  
235      return reinterpret_cast<jlong>(dataSource);
236  }
237  
nativeDestroy(void * ptr)238  void nativeDestroy(void* ptr) {
239      PerfettoDataSource* dataSource = reinterpret_cast<PerfettoDataSource*>(ptr);
240      dataSource->decStrong((void*)nativeCreate);
241  }
242  
nativeGetFinalizer(JNIEnv *,jclass)243  static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
244      return static_cast<jlong>(reinterpret_cast<uintptr_t>(&nativeDestroy));
245  }
246  
nativeWritePackets(JNIEnv * env,jclass clazz,jlong ds_ptr,jobjectArray packets)247  void nativeWritePackets(JNIEnv* env, jclass clazz, jlong ds_ptr, jobjectArray packets) {
248      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(ds_ptr);
249      datasource->WritePackets(env, packets);
250  }
251  
nativeFlushAll(JNIEnv * env,jclass clazz,jlong ptr)252  void nativeFlushAll(JNIEnv* env, jclass clazz, jlong ptr) {
253      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(ptr);
254      datasource->flushAll();
255  }
256  
nativeRegisterDataSource(JNIEnv * env,jclass clazz,jlong datasource_ptr,jint buffer_exhausted_policy,jboolean will_notify_on_stop,jboolean no_flush)257  void nativeRegisterDataSource(JNIEnv* env, jclass clazz, jlong datasource_ptr,
258                                jint buffer_exhausted_policy, jboolean will_notify_on_stop,
259                                jboolean no_flush) {
260      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(datasource_ptr);
261  
262      struct PerfettoDsParams params = PerfettoDsParamsDefault();
263      params.will_notify_on_stop = will_notify_on_stop;
264      params.buffer_exhausted_policy = (PerfettoDsBufferExhaustedPolicy)buffer_exhausted_policy;
265  
266      params.user_arg = reinterpret_cast<void*>(datasource.get());
267  
268      params.on_setup_cb = [](struct PerfettoDsImpl*, PerfettoDsInstanceIndex inst_id,
269                              void* ds_config, size_t ds_config_size, void* user_arg,
270                              struct PerfettoDsOnSetupArgs*) -> void* {
271          JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
272  
273          auto* datasource = reinterpret_cast<PerfettoDataSource*>(user_arg);
274  
275          ScopedLocalRef<jobject> java_data_source_instance(env,
276                                                            datasource->newInstance(env, ds_config,
277                                                                                    ds_config_size,
278                                                                                    inst_id));
279  
280          auto* datasource_instance =
281                  new PerfettoDataSourceInstance(env, java_data_source_instance.get(), inst_id);
282          return static_cast<void*>(datasource_instance);
283      };
284  
285      params.on_create_tls_cb = [](struct PerfettoDsImpl* ds_impl, PerfettoDsInstanceIndex inst_id,
286                                   struct PerfettoDsTracerImpl* tracer, void* user_arg) -> void* {
287          // Populated later and only if required by the java side
288          auto* tls_state = new TlsState(NULL);
289          return static_cast<void*>(tls_state);
290      };
291  
292      params.on_delete_tls_cb = [](void* ptr) {
293          JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
294  
295          TlsState* tls_state = reinterpret_cast<TlsState*>(ptr);
296  
297          if (tls_state->jobj != NULL) {
298              env->DeleteGlobalRef(tls_state->jobj);
299          }
300          delete tls_state;
301      };
302  
303      params.on_create_incr_cb = [](struct PerfettoDsImpl* ds_impl, PerfettoDsInstanceIndex inst_id,
304                                    struct PerfettoDsTracerImpl* tracer, void* user_arg) -> void* {
305          // Populated later and only if required by the java side
306          auto* incr_state = new IncrementalState(NULL);
307          return static_cast<void*>(incr_state);
308      };
309  
310      params.on_delete_incr_cb = [](void* ptr) {
311          JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
312  
313          IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(ptr);
314  
315          if (incr_state->jobj != NULL) {
316              env->DeleteGlobalRef(incr_state->jobj);
317          }
318          delete incr_state;
319      };
320  
321      params.on_start_cb = [](struct PerfettoDsImpl*, PerfettoDsInstanceIndex, void*, void* inst_ctx,
322                              struct PerfettoDsOnStartArgs*) {
323          JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
324  
325          auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
326          datasource_instance->onStart(env);
327      };
328  
329      if (!no_flush) {
330          params.on_flush_cb = [](struct PerfettoDsImpl*, PerfettoDsInstanceIndex, void*,
331                                  void* inst_ctx, struct PerfettoDsOnFlushArgs*) {
332              JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
333  
334              auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
335              datasource_instance->onFlush(env);
336          };
337      }
338  
339      params.on_stop_cb = [](struct PerfettoDsImpl*, PerfettoDsInstanceIndex inst_id, void* user_arg,
340                             void* inst_ctx, struct PerfettoDsOnStopArgs*) {
341          JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
342  
343          auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
344          datasource_instance->onStop(env);
345      };
346  
347      params.on_destroy_cb = [](struct PerfettoDsImpl* ds_impl, void* user_arg,
348                                void* inst_ctx) -> void {
349          auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
350  
351          delete datasource_instance;
352      };
353  
354      PerfettoDsRegister(&datasource->dataSource, datasource->dataSourceName.c_str(), params);
355  }
356  
nativeGetPerfettoInstanceLocked(JNIEnv *,jclass,jlong dataSourcePtr,PerfettoDsInstanceIndex instance_idx)357  jobject nativeGetPerfettoInstanceLocked(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr,
358                                          PerfettoDsInstanceIndex instance_idx) {
359      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
360      auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(
361              PerfettoDsImplGetInstanceLocked(datasource->dataSource.impl, instance_idx));
362  
363      if (datasource_instance == nullptr) {
364          // datasource instance doesn't exist
365          ALOG(LOG_WARN, LOG_TAG,
366               "DS instance invalid!! nativeGetPerfettoInstanceLocked returning NULL");
367          return nullptr;
368      }
369  
370      return datasource_instance->GetJavaDataSourceInstance();
371  }
372  
nativeReleasePerfettoInstanceLocked(JNIEnv *,jclass,jlong dataSourcePtr,PerfettoDsInstanceIndex instance_idx)373  void nativeReleasePerfettoInstanceLocked(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr,
374                                           PerfettoDsInstanceIndex instance_idx) {
375      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
376      PerfettoDsImplReleaseInstanceLocked(datasource->dataSource.impl, instance_idx);
377  }
378  
nativePerfettoDsTraceIterateBegin(JNIEnv *,jclass,jlong dataSourcePtr)379  bool nativePerfettoDsTraceIterateBegin(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
380      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
381      return datasource->TraceIterateBegin();
382  }
383  
nativePerfettoDsTraceIterateNext(JNIEnv *,jclass,jlong dataSourcePtr)384  bool nativePerfettoDsTraceIterateNext(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
385      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
386      return datasource->TraceIterateNext();
387  }
388  
nativePerfettoDsTraceIterateBreak(JNIEnv *,jclass,jlong dataSourcePtr)389  void nativePerfettoDsTraceIterateBreak(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
390      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
391      return datasource->TraceIterateBreak();
392  }
393  
nativeGetPerfettoDsInstanceIndex(JNIEnv *,jclass,jlong dataSourcePtr)394  jint nativeGetPerfettoDsInstanceIndex(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
395      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
396      return (jint)datasource->GetInstanceIndex();
397  }
398  
nativeGetCustomTls(JNIEnv *,jclass,jlong dataSourcePtr)399  jobject nativeGetCustomTls(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
400      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
401      return datasource->GetCustomTls();
402  }
403  
nativeSetCustomTls(JNIEnv * env,jclass,jlong dataSourcePtr,jobject tlsState)404  void nativeSetCustomTls(JNIEnv* env, jclass /* clazz */, jlong dataSourcePtr, jobject tlsState) {
405      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
406      tlsState = env->NewGlobalRef(tlsState);
407      return datasource->SetCustomTls(tlsState);
408  }
409  
nativeGetIncrementalState(JNIEnv *,jclass,jlong dataSourcePtr)410  jobject nativeGetIncrementalState(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
411      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
412      return datasource->GetIncrementalState();
413  }
414  
nativeSetIncrementalState(JNIEnv * env,jclass,jlong dataSourcePtr,jobject incrementalState)415  void nativeSetIncrementalState(JNIEnv* env, jclass /* clazz */, jlong dataSourcePtr,
416                                 jobject incrementalState) {
417      sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
418      incrementalState = env->NewGlobalRef(incrementalState);
419      return datasource->SetIncrementalState(incrementalState);
420  }
421  
422  const JNINativeMethod gMethods[] = {
423          /* name, signature, funcPtr */
424          {"nativeCreate", "(Landroid/tracing/perfetto/DataSource;Ljava/lang/String;)J",
425           (void*)nativeCreate},
426          {"nativeFlushAll", "(J)V", (void*)nativeFlushAll},
427          {"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer},
428          {"nativeRegisterDataSource", "(JIZZ)V", (void*)nativeRegisterDataSource},
429          {"nativeGetPerfettoInstanceLocked", "(JI)Landroid/tracing/perfetto/DataSourceInstance;",
430           (void*)nativeGetPerfettoInstanceLocked},
431          {"nativeReleasePerfettoInstanceLocked", "(JI)V",
432           (void*)nativeReleasePerfettoInstanceLocked},
433  
434          {"nativePerfettoDsTraceIterateBegin", "(J)Z", (void*)nativePerfettoDsTraceIterateBegin},
435          {"nativePerfettoDsTraceIterateNext", "(J)Z", (void*)nativePerfettoDsTraceIterateNext},
436          {"nativePerfettoDsTraceIterateBreak", "(J)V", (void*)nativePerfettoDsTraceIterateBreak},
437          {"nativeGetPerfettoDsInstanceIndex", "(J)I", (void*)nativeGetPerfettoDsInstanceIndex},
438  
439          {"nativeWritePackets", "(J[[B)V", (void*)nativeWritePackets}};
440  
441  const JNINativeMethod gMethodsTracingContext[] = {
442          /* name, signature, funcPtr */
443          {"nativeGetCustomTls", "(J)Ljava/lang/Object;", (void*)nativeGetCustomTls},
444          {"nativeGetIncrementalState", "(J)Ljava/lang/Object;", (void*)nativeGetIncrementalState},
445          {"nativeSetCustomTls", "(JLjava/lang/Object;)V", (void*)nativeSetCustomTls},
446          {"nativeSetIncrementalState", "(JLjava/lang/Object;)V", (void*)nativeSetIncrementalState},
447  };
448  
register_android_tracing_PerfettoDataSource(JNIEnv * env)449  int register_android_tracing_PerfettoDataSource(JNIEnv* env) {
450      int res = jniRegisterNativeMethods(env, "android/tracing/perfetto/DataSource", gMethods,
451                                         NELEM(gMethods));
452  
453      LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
454  
455      res = jniRegisterNativeMethods(env, "android/tracing/perfetto/TracingContext",
456                                     gMethodsTracingContext, NELEM(gMethodsTracingContext));
457  
458      LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
459  
460      if (env->GetJavaVM(&gVm) != JNI_OK) {
461          LOG_ALWAYS_FATAL("Failed to get JavaVM from JNIEnv: %p", env);
462      }
463  
464      jclass clazz = env->FindClass("android/tracing/perfetto/DataSource");
465      gPerfettoDataSourceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
466      gPerfettoDataSourceClassInfo.createInstance =
467              env->GetMethodID(gPerfettoDataSourceClassInfo.clazz, "createInstance",
468                               "([BI)Landroid/tracing/perfetto/DataSourceInstance;");
469      gPerfettoDataSourceClassInfo.createTlsState =
470              env->GetMethodID(gPerfettoDataSourceClassInfo.clazz, "createTlsState",
471                               "(Landroid/tracing/perfetto/CreateTlsStateArgs;)Ljava/lang/Object;");
472      gPerfettoDataSourceClassInfo.createIncrementalState =
473              env->GetMethodID(gPerfettoDataSourceClassInfo.clazz, "createIncrementalState",
474                               "(Landroid/tracing/perfetto/CreateIncrementalStateArgs;)Ljava/lang/"
475                               "Object;");
476  
477      clazz = env->FindClass("android/tracing/perfetto/CreateTlsStateArgs");
478      gCreateTlsStateArgsClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
479      gCreateTlsStateArgsClassInfo.init =
480              env->GetMethodID(gCreateTlsStateArgsClassInfo.clazz, "<init>",
481                               "(Landroid/tracing/perfetto/DataSource;I)V");
482  
483      clazz = env->FindClass("android/tracing/perfetto/CreateIncrementalStateArgs");
484      gCreateIncrementalStateArgsClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
485      gCreateIncrementalStateArgsClassInfo.init =
486              env->GetMethodID(gCreateIncrementalStateArgsClassInfo.clazz, "<init>",
487                               "(Landroid/tracing/perfetto/DataSource;I)V");
488  
489      return 0;
490  }
491  
492  } // namespace android