1 /*
2 * Copyright 2022 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 "TaskFpsCallbackController"
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 } gCallbackClassInfo;
39
40 struct TaskFpsCallback : public gui::BnFpsListener {
TaskFpsCallbackandroid::__anona19ea1690111::TaskFpsCallback41 TaskFpsCallback(JNIEnv* env, jobject listener) : mListener(env->NewWeakGlobalRef(listener)) {}
42
onFpsReportedandroid::__anona19ea1690111::TaskFpsCallback43 binder::Status onFpsReported(float fps) override {
44 JNIEnv* env = AndroidRuntime::getJNIEnv();
45 LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onFpsReported.");
46
47 jobject listener = env->NewGlobalRef(mListener);
48 if (listener == NULL) {
49 // Weak reference went out of scope
50 return binder::Status::ok();
51 }
52 env->CallStaticVoidMethod(gCallbackClassInfo.mClass,
53 gCallbackClassInfo.mDispatchOnFpsReported, listener,
54 static_cast<jfloat>(fps));
55 env->DeleteGlobalRef(listener);
56
57 if (env->ExceptionCheck()) {
58 ALOGE("TaskFpsCallback.onFpsReported() failed.");
59 LOGE_EX(env);
60 env->ExceptionClear();
61 }
62 return binder::Status::ok();
63 }
64
65 protected:
~TaskFpsCallbackandroid::__anona19ea1690111::TaskFpsCallback66 virtual ~TaskFpsCallback() {
67 JNIEnv* env = AndroidRuntime::getJNIEnv();
68 env->DeleteWeakGlobalRef(mListener);
69 }
70
71 private:
72 jweak mListener;
73 };
74
nativeRegister(JNIEnv * env,jclass clazz,jobject obj,jint taskId)75 jlong nativeRegister(JNIEnv* env, jclass clazz, jobject obj, jint taskId) {
76 TaskFpsCallback* callback = new TaskFpsCallback(env, obj);
77
78 if (SurfaceComposerClient::addFpsListener(taskId, callback) != OK) {
79 constexpr auto error_msg = "Couldn't addFpsListener";
80 ALOGE(error_msg);
81 jniThrowRuntimeException(env, error_msg);
82 }
83 callback->incStrong((void*)nativeRegister);
84
85 return reinterpret_cast<jlong>(callback);
86 }
87
nativeUnregister(JNIEnv * env,jclass clazz,jlong ptr)88 void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
89 sp<TaskFpsCallback> callback = reinterpret_cast<TaskFpsCallback*>(ptr);
90
91 if (SurfaceComposerClient::removeFpsListener(callback) != OK) {
92 constexpr auto error_msg = "Couldn't removeFpsListener";
93 ALOGE(error_msg);
94 jniThrowRuntimeException(env, error_msg);
95 }
96
97 callback->decStrong((void*)nativeRegister);
98 }
99
100 static const JNINativeMethod gMethods[] = {
101 /* name, signature, funcPtr */
102 {"nativeRegister", "(Landroid/window/ITaskFpsCallback;I)J", (void*)nativeRegister},
103 {"nativeUnregister", "(J)V", (void*)nativeUnregister}};
104
105 } // namespace
106
register_com_android_server_wm_TaskFpsCallbackController(JNIEnv * env)107 int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env) {
108 int res = jniRegisterNativeMethods(env, "com/android/server/wm/TaskFpsCallbackController",
109 gMethods, NELEM(gMethods));
110 LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
111
112 jclass clazz = env->FindClass("android/window/TaskFpsCallback");
113 gCallbackClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
114 gCallbackClassInfo.mDispatchOnFpsReported =
115 env->GetStaticMethodID(clazz, "dispatchOnFpsReported",
116 "(Landroid/window/ITaskFpsCallback;F)V");
117 return 0;
118 }
119
120 } // namespace android
121