1 /*
2  * Copyright (C) 2011 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 "InputApplicationHandle"
18 
19 #include "JNIHelp.h"
20 #include "jni.h"
21 #include <android_runtime/AndroidRuntime.h>
22 #include <utils/threads.h>
23 
24 #include "com_android_server_input_InputApplicationHandle.h"
25 
26 namespace android {
27 
28 static struct {
29     jfieldID ptr;
30     jfieldID name;
31     jfieldID dispatchingTimeoutNanos;
32 } gInputApplicationHandleClassInfo;
33 
34 static Mutex gHandleMutex;
35 
36 
37 // --- NativeInputApplicationHandle ---
38 
NativeInputApplicationHandle(jweak objWeak)39 NativeInputApplicationHandle::NativeInputApplicationHandle(jweak objWeak) :
40         mObjWeak(objWeak) {
41 }
42 
~NativeInputApplicationHandle()43 NativeInputApplicationHandle::~NativeInputApplicationHandle() {
44     JNIEnv* env = AndroidRuntime::getJNIEnv();
45     env->DeleteWeakGlobalRef(mObjWeak);
46 }
47 
getInputApplicationHandleObjLocalRef(JNIEnv * env)48 jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEnv* env) {
49     return env->NewLocalRef(mObjWeak);
50 }
51 
updateInfo()52 bool NativeInputApplicationHandle::updateInfo() {
53     JNIEnv* env = AndroidRuntime::getJNIEnv();
54     jobject obj = env->NewLocalRef(mObjWeak);
55     if (!obj) {
56         releaseInfo();
57         return false;
58     }
59 
60     if (!mInfo) {
61         mInfo = new InputApplicationInfo();
62     }
63 
64     jstring nameObj = jstring(env->GetObjectField(obj,
65             gInputApplicationHandleClassInfo.name));
66     if (nameObj) {
67         const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
68         mInfo->name.setTo(nameStr);
69         env->ReleaseStringUTFChars(nameObj, nameStr);
70         env->DeleteLocalRef(nameObj);
71     } else {
72         mInfo->name.setTo("<null>");
73     }
74 
75     mInfo->dispatchingTimeout = env->GetLongField(obj,
76             gInputApplicationHandleClassInfo.dispatchingTimeoutNanos);
77 
78     env->DeleteLocalRef(obj);
79     return true;
80 }
81 
82 
83 // --- Global functions ---
84 
android_server_InputApplicationHandle_getHandle(JNIEnv * env,jobject inputApplicationHandleObj)85 sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
86         JNIEnv* env, jobject inputApplicationHandleObj) {
87     if (!inputApplicationHandleObj) {
88         return NULL;
89     }
90 
91     AutoMutex _l(gHandleMutex);
92 
93     jlong ptr = env->GetLongField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr);
94     NativeInputApplicationHandle* handle;
95     if (ptr) {
96         handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
97     } else {
98         jweak objWeak = env->NewWeakGlobalRef(inputApplicationHandleObj);
99         handle = new NativeInputApplicationHandle(objWeak);
100         handle->incStrong((void*)android_server_InputApplicationHandle_getHandle);
101         env->SetLongField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr,
102                 reinterpret_cast<jlong>(handle));
103     }
104     return handle;
105 }
106 
107 
108 // --- JNI ---
109 
android_server_InputApplicationHandle_nativeDispose(JNIEnv * env,jobject obj)110 static void android_server_InputApplicationHandle_nativeDispose(JNIEnv* env, jobject obj) {
111     AutoMutex _l(gHandleMutex);
112 
113     jlong ptr = env->GetLongField(obj, gInputApplicationHandleClassInfo.ptr);
114     if (ptr) {
115         env->SetLongField(obj, gInputApplicationHandleClassInfo.ptr, 0);
116 
117         NativeInputApplicationHandle* handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
118         handle->decStrong((void*)android_server_InputApplicationHandle_getHandle);
119     }
120 }
121 
122 
123 static const JNINativeMethod gInputApplicationHandleMethods[] = {
124     /* name, signature, funcPtr */
125     { "nativeDispose", "()V",
126             (void*) android_server_InputApplicationHandle_nativeDispose },
127 };
128 
129 #define FIND_CLASS(var, className) \
130         var = env->FindClass(className); \
131         LOG_FATAL_IF(! var, "Unable to find class " className);
132 
133 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
134         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
135         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
136 
register_android_server_InputApplicationHandle(JNIEnv * env)137 int register_android_server_InputApplicationHandle(JNIEnv* env) {
138     int res = jniRegisterNativeMethods(env, "com/android/server/input/InputApplicationHandle",
139             gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
140     (void) res;  // Faked use when LOG_NDEBUG.
141     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
142 
143     jclass clazz;
144     FIND_CLASS(clazz, "com/android/server/input/InputApplicationHandle");
145 
146     GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
147             "ptr", "J");
148 
149     GET_FIELD_ID(gInputApplicationHandleClassInfo.name, clazz,
150             "name", "Ljava/lang/String;");
151 
152     GET_FIELD_ID(gInputApplicationHandleClassInfo.dispatchingTimeoutNanos,
153             clazz,
154             "dispatchingTimeoutNanos", "J");
155 
156     return 0;
157 }
158 
159 } /* namespace android */
160