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