1 /*
2  * Copyright (C) 2024 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 "InputTransferToken"
18 
19 #include <android_runtime/android_window_InputTransferToken.h>
20 #include <gui/InputTransferToken.h>
21 #include <nativehelper/JNIHelp.h>
22 
23 #include "android_os_Parcel.h"
24 #include "android_util_Binder.h"
25 #include "core_jni_helpers.h"
26 
27 namespace android {
28 
29 static struct {
30     jclass clazz;
31     jfieldID mNativeObject;
32     jmethodID ctor;
33 } gInputTransferTokenClassInfo;
34 
nativeCreate(JNIEnv * env,jclass clazz)35 static jlong nativeCreate(JNIEnv* env, jclass clazz) {
36     sp<InputTransferToken> inputTransferToken = sp<InputTransferToken>::make();
37     inputTransferToken->incStrong((void*)nativeCreate);
38     return reinterpret_cast<jlong>(inputTransferToken.get());
39 }
40 
nativeCreateFromBinder(JNIEnv * env,jclass clazz,jobject tokenBinderObj)41 static jlong nativeCreateFromBinder(JNIEnv* env, jclass clazz, jobject tokenBinderObj) {
42     if (tokenBinderObj == nullptr) {
43         return 0;
44     }
45     sp<IBinder> token(ibinderForJavaObject(env, tokenBinderObj));
46     if (token == nullptr) {
47         return 0;
48     }
49     sp<InputTransferToken> inputTransferToken = sp<InputTransferToken>::make(token);
50     inputTransferToken->incStrong((void*)nativeCreate);
51     return reinterpret_cast<jlong>(inputTransferToken.get());
52 }
53 
nativeWriteToParcel(JNIEnv * env,jclass clazz,jlong nativeObj,jobject parcelObj)54 static void nativeWriteToParcel(JNIEnv* env, jclass clazz, jlong nativeObj, jobject parcelObj) {
55     InputTransferToken* inputTransferToken = reinterpret_cast<InputTransferToken*>(nativeObj);
56     Parcel* parcel = parcelForJavaObject(env, parcelObj);
57     inputTransferToken->writeToParcel(parcel);
58 }
59 
nativeReadFromParcel(JNIEnv * env,jclass clazz,jobject parcelObj)60 static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) {
61     sp<InputTransferToken> inputTransferToken = sp<InputTransferToken>::make();
62     Parcel* parcel = parcelForJavaObject(env, parcelObj);
63     inputTransferToken->readFromParcel(parcel);
64     inputTransferToken->incStrong((void*)nativeCreate);
65     return reinterpret_cast<jlong>(inputTransferToken.get());
66 }
67 
nativeGetBinderToken(JNIEnv * env,jclass clazz,jlong nativeObj)68 static jobject nativeGetBinderToken(JNIEnv* env, jclass clazz, jlong nativeObj) {
69     sp<InputTransferToken> inputTransferToken = reinterpret_cast<InputTransferToken*>(nativeObj);
70     return javaObjectForIBinder(env, inputTransferToken->mToken);
71 }
72 
nativeGetBinderTokenRef(JNIEnv *,jclass,jlong nativeObj)73 static jlong nativeGetBinderTokenRef(JNIEnv*, jclass, jlong nativeObj) {
74     sp<InputTransferToken> inputTransferToken = reinterpret_cast<InputTransferToken*>(nativeObj);
75     return reinterpret_cast<jlong>(inputTransferToken->mToken.get());
76 }
77 
android_window_InputTransferToken_getNativeInputTransferToken(JNIEnv * env,jobject inputTransferTokenObj)78 InputTransferToken* android_window_InputTransferToken_getNativeInputTransferToken(
79         JNIEnv* env, jobject inputTransferTokenObj) {
80     if (inputTransferTokenObj != nullptr &&
81         env->IsInstanceOf(inputTransferTokenObj, gInputTransferTokenClassInfo.clazz)) {
82         return reinterpret_cast<InputTransferToken*>(
83                 env->GetLongField(inputTransferTokenObj,
84                                   gInputTransferTokenClassInfo.mNativeObject));
85     } else {
86         return nullptr;
87     }
88 }
89 
android_window_InputTransferToken_getJavaInputTransferToken(JNIEnv * env,const InputTransferToken & inputTransferToken)90 jobject android_window_InputTransferToken_getJavaInputTransferToken(
91         JNIEnv* env, const InputTransferToken& inputTransferToken) {
92     inputTransferToken.incStrong((void*)nativeCreate);
93     return env->NewObject(gInputTransferTokenClassInfo.clazz, gInputTransferTokenClassInfo.ctor,
94                           reinterpret_cast<jlong>(&inputTransferToken));
95 }
96 
release(InputTransferToken * inputTransferToken)97 static void release(InputTransferToken* inputTransferToken) {
98     inputTransferToken->decStrong((void*)nativeCreate);
99 }
100 
nativeGetNativeInputTransferTokenFinalizer(JNIEnv * env,jclass clazz)101 static jlong nativeGetNativeInputTransferTokenFinalizer(JNIEnv* env, jclass clazz) {
102     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&release));
103 }
104 
nativeEquals(JNIEnv * env,jclass clazz,jlong inputTransferTokenObj1,jlong inputTransferTokenObj2)105 static bool nativeEquals(JNIEnv* env, jclass clazz, jlong inputTransferTokenObj1,
106                          jlong inputTransferTokenObj2) {
107     sp<InputTransferToken> inputTransferToken1(
108             reinterpret_cast<InputTransferToken*>(inputTransferTokenObj1));
109     sp<InputTransferToken> inputTransferToken2(
110             reinterpret_cast<InputTransferToken*>(inputTransferTokenObj2));
111 
112     return inputTransferToken1 == inputTransferToken2;
113 }
114 
115 static const JNINativeMethod sInputTransferTokenMethods[] = {
116         // clang-format off
117     {"nativeCreate", "()J", (void*)nativeCreate},
118     {"nativeCreate", "(Landroid/os/IBinder;)J", (void*)nativeCreateFromBinder},
119     {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel},
120     {"nativeReadFromParcel", "(Landroid/os/Parcel;)J", (void*)nativeReadFromParcel},
121     {"nativeGetBinderToken", "(J)Landroid/os/IBinder;", (void*)nativeGetBinderToken},
122     {"nativeGetBinderTokenRef", "(J)J", (void*)nativeGetBinderTokenRef},
123     {"nativeGetNativeInputTransferTokenFinalizer", "()J", (void*)nativeGetNativeInputTransferTokenFinalizer},
124         {"nativeEquals", "(JJ)Z", (void*) nativeEquals},
125         // clang-format on
126 };
127 
register_android_window_InputTransferToken(JNIEnv * env)128 int register_android_window_InputTransferToken(JNIEnv* env) {
129     int err = RegisterMethodsOrDie(env, "android/window/InputTransferToken",
130                                    sInputTransferTokenMethods, NELEM(sInputTransferTokenMethods));
131     jclass inputTransferTokenClass = FindClassOrDie(env, "android/window/InputTransferToken");
132     gInputTransferTokenClassInfo.clazz = MakeGlobalRefOrDie(env, inputTransferTokenClass);
133     gInputTransferTokenClassInfo.mNativeObject =
134             GetFieldIDOrDie(env, gInputTransferTokenClassInfo.clazz, "mNativeObject", "J");
135     gInputTransferTokenClassInfo.ctor =
136             GetMethodIDOrDie(env, gInputTransferTokenClassInfo.clazz, "<init>", "(J)V");
137     return err;
138 }
139 
140 } // namespace android