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 "WindowInfosListener"
18
19 #include <android_runtime/AndroidRuntime.h>
20 #include <android_runtime/Log.h>
21 #include <gui/SurfaceComposerClient.h>
22 #include <nativehelper/JNIHelp.h>
23 #include <utils/Log.h>
24
25 #include "android_hardware_input_InputWindowHandle.h"
26 #include "core_jni_helpers.h"
27
28 namespace android {
29
30 using gui::WindowInfo;
31
32 namespace {
33
34 static struct {
35 jclass clazz;
36 jmethodID onWindowInfosChanged;
37 } gListenerClassInfo;
38
39 static jclass gInputWindowHandleClass;
40
41 struct WindowInfosListener : public gui::WindowInfosListener {
WindowInfosListenerandroid::__anon1be1e6920110::WindowInfosListener42 WindowInfosListener(JNIEnv* env, jobject listener)
43 : mListener(env->NewWeakGlobalRef(listener)) {}
44
onWindowInfosChangedandroid::__anon1be1e6920110::WindowInfosListener45 void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos) override {
46 JNIEnv* env = AndroidRuntime::getJNIEnv();
47 LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onWindowInfoChanged.");
48
49 jobject listener = env->NewGlobalRef(mListener);
50 if (listener == nullptr) {
51 // Weak reference went out of scope
52 return;
53 }
54
55 jobjectArray jWindowHandlesArray =
56 env->NewObjectArray(windowInfos.size(), gInputWindowHandleClass, nullptr);
57 for (int i = 0; i < windowInfos.size(); i++) {
58 ScopedLocalRef<jobject>
59 jWindowHandle(env,
60 android_view_InputWindowHandle_fromWindowInfo(env,
61 windowInfos[i]));
62 env->SetObjectArrayElement(jWindowHandlesArray, i, jWindowHandle.get());
63 }
64
65 env->CallVoidMethod(listener, gListenerClassInfo.onWindowInfosChanged, jWindowHandlesArray);
66 env->DeleteGlobalRef(listener);
67
68 if (env->ExceptionCheck()) {
69 ALOGE("WindowInfosListener.onWindowInfosChanged() failed.");
70 LOGE_EX(env);
71 env->ExceptionClear();
72 }
73 }
74
~WindowInfosListenerandroid::__anon1be1e6920110::WindowInfosListener75 ~WindowInfosListener() override {
76 JNIEnv* env = AndroidRuntime::getJNIEnv();
77 env->DeleteWeakGlobalRef(mListener);
78 }
79
80 private:
81 jweak mListener;
82 };
83
nativeCreate(JNIEnv * env,jclass clazz,jobject obj)84 jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
85 WindowInfosListener* listener = new WindowInfosListener(env, obj);
86 listener->incStrong((void*)nativeCreate);
87 return reinterpret_cast<jlong>(listener);
88 }
89
destroyNativeService(void * ptr)90 void destroyNativeService(void* ptr) {
91 WindowInfosListener* listener = reinterpret_cast<WindowInfosListener*>(ptr);
92 listener->decStrong((void*)nativeCreate);
93 }
94
nativeRegister(JNIEnv * env,jclass clazz,jlong ptr)95 void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) {
96 sp<WindowInfosListener> listener = reinterpret_cast<WindowInfosListener*>(ptr);
97 SurfaceComposerClient::getDefault()->addWindowInfosListener(listener);
98 }
99
nativeUnregister(JNIEnv * env,jclass clazz,jlong ptr)100 void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
101 sp<WindowInfosListener> listener = reinterpret_cast<WindowInfosListener*>(ptr);
102 SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener);
103 }
104
nativeGetFinalizer(JNIEnv *,jclass)105 static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
106 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeService));
107 }
108
109 const JNINativeMethod gMethods[] = {
110 /* name, signature, funcPtr */
111 {"nativeCreate", "(Landroid/window/WindowInfosListener;)J", (void*)nativeCreate},
112 {"nativeRegister", "(J)V", (void*)nativeRegister},
113 {"nativeUnregister", "(J)V", (void*)nativeUnregister},
114 {"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer}};
115
116 } // namespace
117
register_android_window_WindowInfosListener(JNIEnv * env)118 int register_android_window_WindowInfosListener(JNIEnv* env) {
119 int res = jniRegisterNativeMethods(env, "android/window/WindowInfosListener", gMethods,
120 NELEM(gMethods));
121 LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
122
123 jclass clazz = env->FindClass("android/window/WindowInfosListener");
124 gListenerClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
125 gListenerClassInfo.onWindowInfosChanged =
126 env->GetMethodID(gListenerClassInfo.clazz, "onWindowInfosChanged",
127 "([Landroid/view/InputWindowHandle;)V");
128
129 clazz = env->FindClass("android/view/InputWindowHandle");
130 gInputWindowHandleClass = MakeGlobalRefOrDie(env, clazz);
131 return 0;
132 }
133
134 } // namespace android
135