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