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 "SurfaceControlHdrLayerInfoListener"
18
19 #include <android/gui/BnHdrLayerInfoListener.h>
20 #include <android_runtime/Log.h>
21 #include <gui/ISurfaceComposer.h>
22 #include <gui/SurfaceComposerClient.h>
23 #include <log/log.h>
24 #include <nativehelper/JNIHelp.h>
25 #include <utils/RefBase.h>
26
27 #include "android_util_Binder.h"
28 #include "core_jni_helpers.h"
29
30 namespace android {
31
32 namespace {
33
34 struct {
35 jclass mClass;
36 jmethodID mOnHdrInfoChanged;
37 } gListenerClassInfo;
38
39 struct SurfaceControlHdrLayerInfoListener : public gui::BnHdrLayerInfoListener {
SurfaceControlHdrLayerInfoListenerandroid::__anoneb3ed3f10110::SurfaceControlHdrLayerInfoListener40 SurfaceControlHdrLayerInfoListener(JNIEnv* env, jobject listener, jobject displayToken)
41 : mListener(env->NewGlobalRef(listener)), mDisplayToken(env->NewGlobalRef(displayToken)) {
42 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mVm) != JNI_OK, "Failed to GetJavaVm");
43 }
44
onHdrLayerInfoChangedandroid::__anoneb3ed3f10110::SurfaceControlHdrLayerInfoListener45 binder::Status onHdrLayerInfoChanged(int numberOfHdrLayers, int maxW, int maxH, int flags,
46 float maxDesiredHdrSdrRatio) override {
47 JNIEnv* env = requireEnv();
48
49 env->CallVoidMethod(mListener, gListenerClassInfo.mOnHdrInfoChanged, mDisplayToken,
50 numberOfHdrLayers, maxW, maxH, flags, maxDesiredHdrSdrRatio);
51
52 if (env->ExceptionCheck()) {
53 ALOGE("SurfaceControlHdrLayerInfoListener.onHdrInfoChanged() failed.");
54 LOGE_EX(env);
55 env->ExceptionClear();
56 }
57 return binder::Status::ok();
58 }
59
startListeningandroid::__anoneb3ed3f10110::SurfaceControlHdrLayerInfoListener60 status_t startListening() {
61 auto token = ibinderForJavaObject(requireEnv(), mDisplayToken);
62 return SurfaceComposerClient::addHdrLayerInfoListener(token, this);
63 }
64
stopListeningandroid::__anoneb3ed3f10110::SurfaceControlHdrLayerInfoListener65 status_t stopListening() {
66 auto token = ibinderForJavaObject(requireEnv(), mDisplayToken);
67 return SurfaceComposerClient::removeHdrLayerInfoListener(token, this);
68 }
69
70 protected:
~SurfaceControlHdrLayerInfoListenerandroid::__anoneb3ed3f10110::SurfaceControlHdrLayerInfoListener71 virtual ~SurfaceControlHdrLayerInfoListener() {
72 JNIEnv* env = requireEnv();
73 env->DeleteGlobalRef(mListener);
74 env->DeleteGlobalRef(mDisplayToken);
75 }
76
requireEnvandroid::__anoneb3ed3f10110::SurfaceControlHdrLayerInfoListener77 JNIEnv* requireEnv() {
78 JNIEnv* env = nullptr;
79 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
80 if (mVm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
81 LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
82 }
83 }
84 return env;
85 }
86
87 private:
88 jobject mListener;
89 jobject mDisplayToken;
90 JavaVM* mVm;
91 };
92
nRegister(JNIEnv * env,jobject jthis,jobject jbinderToken)93 jlong nRegister(JNIEnv* env, jobject jthis, jobject jbinderToken) {
94 auto callback = sp<SurfaceControlHdrLayerInfoListener>::make(env, jthis, jbinderToken);
95 status_t err = callback->startListening();
96 if (err != OK) {
97 auto errStr = statusToString(err);
98 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
99 "Failed to register HdrLayerInfoListener, err = %d (%s)", err,
100 errStr.c_str());
101 return 0;
102 }
103 SurfaceControlHdrLayerInfoListener* ret = callback.get();
104 ret->incStrong(0);
105 return static_cast<jlong>(reinterpret_cast<intptr_t>(ret));
106 }
107
destroy(SurfaceControlHdrLayerInfoListener * listener)108 static void destroy(SurfaceControlHdrLayerInfoListener* listener) {
109 listener->stopListening();
110 listener->decStrong(0);
111 }
112
nGetDestructor(JNIEnv * env,jobject clazz)113 static jlong nGetDestructor(JNIEnv* env, jobject clazz) {
114 return static_cast<jlong>(reinterpret_cast<intptr_t>(&destroy));
115 }
116
117 const JNINativeMethod gMethods[] = {
118 /* name, signature, funcPtr */
119 {"nGetDestructor", "()J", (void*)nGetDestructor},
120 {"nRegister", "(Landroid/os/IBinder;)J", (void*)nRegister}};
121
122 } // namespace
123
register_android_view_SurfaceControlHdrLayerInfoListener(JNIEnv * env)124 int register_android_view_SurfaceControlHdrLayerInfoListener(JNIEnv* env) {
125 int res = jniRegisterNativeMethods(env, "android/view/SurfaceControlHdrLayerInfoListener",
126 gMethods, NELEM(gMethods));
127 LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
128
129 jclass clazz = env->FindClass("android/view/SurfaceControlHdrLayerInfoListener");
130 gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
131 gListenerClassInfo.mOnHdrInfoChanged =
132 env->GetMethodID(clazz, "onHdrInfoChanged", "(Landroid/os/IBinder;IIIIF)V");
133 return 0;
134 }
135
136 } // namespace android
137