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 "Perfetto"
18
19 #include "android_tracing_PerfettoDataSourceInstance.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 init;
41 } gStartCallbackArgumentsClassInfo;
42
43 static struct {
44 jclass clazz;
45 jmethodID init;
46 } gFlushCallbackArgumentsClassInfo;
47
48 static struct {
49 jclass clazz;
50 jmethodID init;
51 } gStopCallbackArgumentsClassInfo;
52
53 static JavaVM* gVm;
54
callJavaMethodWithArgsObject(JNIEnv * env,jobject classRef,jmethodID method,jobject args)55 void callJavaMethodWithArgsObject(JNIEnv* env, jobject classRef, jmethodID method, jobject args) {
56 ScopedLocalRef<jobject> localClassRef(env, env->NewLocalRef(classRef));
57
58 if (localClassRef == nullptr) {
59 ALOGE("Weak reference went out of scope");
60 return;
61 }
62
63 env->CallVoidMethod(localClassRef.get(), method, args);
64
65 if (env->ExceptionCheck()) {
66 env->ExceptionDescribe();
67 LOGE_EX(env);
68 env->ExceptionClear();
69 }
70 }
71
PerfettoDataSourceInstance(JNIEnv * env,jobject javaDataSourceInstance,PerfettoDsInstanceIndex inst_idx)72 PerfettoDataSourceInstance::PerfettoDataSourceInstance(JNIEnv* env, jobject javaDataSourceInstance,
73 PerfettoDsInstanceIndex inst_idx)
74 : inst_idx(inst_idx), mJavaDataSourceInstance(env->NewGlobalRef(javaDataSourceInstance)) {}
75
~PerfettoDataSourceInstance()76 PerfettoDataSourceInstance::~PerfettoDataSourceInstance() {
77 JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
78 env->DeleteGlobalRef(mJavaDataSourceInstance);
79 }
80
onStart(JNIEnv * env)81 void PerfettoDataSourceInstance::onStart(JNIEnv* env) {
82 ScopedLocalRef<jobject> args(env,
83 env->NewObject(gStartCallbackArgumentsClassInfo.clazz,
84 gStartCallbackArgumentsClassInfo.init));
85 jclass cls = env->GetObjectClass(mJavaDataSourceInstance);
86 jmethodID mid = env->GetMethodID(cls, "onStart",
87 "(Landroid/tracing/perfetto/StartCallbackArguments;)V");
88
89 callJavaMethodWithArgsObject(env, mJavaDataSourceInstance, mid, args.get());
90 }
91
onFlush(JNIEnv * env)92 void PerfettoDataSourceInstance::onFlush(JNIEnv* env) {
93 ScopedLocalRef<jobject> args(env,
94 env->NewObject(gFlushCallbackArgumentsClassInfo.clazz,
95 gFlushCallbackArgumentsClassInfo.init));
96 jclass cls = env->GetObjectClass(mJavaDataSourceInstance);
97 jmethodID mid = env->GetMethodID(cls, "onFlush",
98 "(Landroid/tracing/perfetto/FlushCallbackArguments;)V");
99
100 callJavaMethodWithArgsObject(env, mJavaDataSourceInstance, mid, args.get());
101 }
102
onStop(JNIEnv * env)103 void PerfettoDataSourceInstance::onStop(JNIEnv* env) {
104 ScopedLocalRef<jobject> args(env,
105 env->NewObject(gStopCallbackArgumentsClassInfo.clazz,
106 gStopCallbackArgumentsClassInfo.init));
107 jclass cls = env->GetObjectClass(mJavaDataSourceInstance);
108 jmethodID mid =
109 env->GetMethodID(cls, "onStop", "(Landroid/tracing/perfetto/StopCallbackArguments;)V");
110
111 callJavaMethodWithArgsObject(env, mJavaDataSourceInstance, mid, args.get());
112 }
113
register_android_tracing_PerfettoDataSourceInstance(JNIEnv * env)114 int register_android_tracing_PerfettoDataSourceInstance(JNIEnv* env) {
115 if (env->GetJavaVM(&gVm) != JNI_OK) {
116 LOG_ALWAYS_FATAL("Failed to get JavaVM from JNIEnv: %p", env);
117 }
118
119 jclass clazz = env->FindClass("android/tracing/perfetto/StartCallbackArguments");
120 gStartCallbackArgumentsClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
121 gStartCallbackArgumentsClassInfo.init =
122 env->GetMethodID(gStartCallbackArgumentsClassInfo.clazz, "<init>", "()V");
123
124 clazz = env->FindClass("android/tracing/perfetto/FlushCallbackArguments");
125 gFlushCallbackArgumentsClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
126 gFlushCallbackArgumentsClassInfo.init =
127 env->GetMethodID(gFlushCallbackArgumentsClassInfo.clazz, "<init>", "()V");
128
129 clazz = env->FindClass("android/tracing/perfetto/StopCallbackArguments");
130 gStopCallbackArgumentsClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
131 gStopCallbackArgumentsClassInfo.init =
132 env->GetMethodID(gStopCallbackArgumentsClassInfo.clazz, "<init>", "()V");
133
134 return 0;
135 }
136
137 } // namespace android