1 /*
2 * Copyright 2021 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 "SurfaceControlFpsListener"
18
19 #include <android/gui/BnFpsListener.h>
20 #include <android_runtime/AndroidRuntime.h>
21 #include <android_runtime/Log.h>
22 #include <gui/ISurfaceComposer.h>
23 #include <gui/SurfaceComposerClient.h>
24 #include <nativehelper/JNIHelp.h>
25 #include <utils/Log.h>
26 #include <utils/RefBase.h>
27
28 #include "android_util_Binder.h"
29 #include "core_jni_helpers.h"
30
31 namespace android {
32
33 namespace {
34
35 struct {
36 jclass mClass;
37 jmethodID mDispatchOnFpsReported;
38 } gListenerClassInfo;
39
40 struct SurfaceControlFpsListener : public gui::BnFpsListener {
SurfaceControlFpsListenerandroid::__anon51c1f4f10110::SurfaceControlFpsListener41 SurfaceControlFpsListener(JNIEnv* env, jobject listener)
42 : mListener(env->NewWeakGlobalRef(listener)) {}
43
onFpsReportedandroid::__anon51c1f4f10110::SurfaceControlFpsListener44 binder::Status onFpsReported(float fps) override {
45 JNIEnv* env = AndroidRuntime::getJNIEnv();
46 LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onFpsReported.");
47
48 jobject listener = env->NewGlobalRef(mListener);
49 if (listener == NULL) {
50 // Weak reference went out of scope
51 return binder::Status::ok();
52 }
53 env->CallStaticVoidMethod(gListenerClassInfo.mClass,
54 gListenerClassInfo.mDispatchOnFpsReported, listener,
55 static_cast<jfloat>(fps));
56 env->DeleteGlobalRef(listener);
57
58 if (env->ExceptionCheck()) {
59 ALOGE("SurfaceControlFpsListener.onFpsReported() failed.");
60 LOGE_EX(env);
61 env->ExceptionClear();
62 }
63 return binder::Status::ok();
64 }
65
66 protected:
~SurfaceControlFpsListenerandroid::__anon51c1f4f10110::SurfaceControlFpsListener67 virtual ~SurfaceControlFpsListener() {
68 JNIEnv* env = AndroidRuntime::getJNIEnv();
69 env->DeleteWeakGlobalRef(mListener);
70 }
71
72 private:
73 jweak mListener;
74 };
75
nativeCreate(JNIEnv * env,jclass clazz,jobject obj)76 jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
77 SurfaceControlFpsListener* listener = new SurfaceControlFpsListener(env, obj);
78 listener->incStrong((void*)nativeCreate);
79 return reinterpret_cast<jlong>(listener);
80 }
81
nativeDestroy(JNIEnv * env,jclass clazz,jlong ptr)82 void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
83 SurfaceControlFpsListener* listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
84 listener->decStrong((void*)nativeCreate);
85 }
86
nativeRegister(JNIEnv * env,jclass clazz,jlong ptr,jint taskId)87 void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jint taskId) {
88 sp<SurfaceControlFpsListener> listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
89 if (SurfaceComposerClient::addFpsListener(taskId, listener) != OK) {
90 constexpr auto error_msg = "Couldn't addFpsListener";
91 ALOGE(error_msg);
92 jniThrowRuntimeException(env, error_msg);
93 }
94 }
95
nativeUnregister(JNIEnv * env,jclass clazz,jlong ptr)96 void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
97 sp<SurfaceControlFpsListener> listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
98
99 if (SurfaceComposerClient::removeFpsListener(listener) != OK) {
100 constexpr auto error_msg = "Couldn't removeFpsListener";
101 ALOGE(error_msg);
102 jniThrowRuntimeException(env, error_msg);
103 }
104 }
105
106 const JNINativeMethod gMethods[] = {
107 /* name, signature, funcPtr */
108 {"nativeCreate", "(Landroid/view/SurfaceControlFpsListener;)J", (void*)nativeCreate},
109 {"nativeDestroy", "(J)V", (void*)nativeDestroy},
110 {"nativeRegister", "(JI)V", (void*)nativeRegister},
111 {"nativeUnregister", "(J)V", (void*)nativeUnregister}};
112
113 } // namespace
114
register_android_view_SurfaceControlFpsListener(JNIEnv * env)115 int register_android_view_SurfaceControlFpsListener(JNIEnv* env) {
116 int res = jniRegisterNativeMethods(env, "android/view/SurfaceControlFpsListener", gMethods,
117 NELEM(gMethods));
118 LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
119
120 jclass clazz = env->FindClass("android/view/SurfaceControlFpsListener");
121 gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
122 gListenerClassInfo.mDispatchOnFpsReported =
123 env->GetStaticMethodID(clazz, "dispatchOnFpsReported",
124 "(Landroid/view/SurfaceControlFpsListener;F)V");
125 return 0;
126 }
127
128 } // namespace android
129