• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "InputWindowHandle"
18 
19 #include <nativehelper/JNIHelp.h>
20 #include "core_jni_helpers.h"
21 #include "jni.h"
22 #include <android_runtime/AndroidRuntime.h>
23 #include <utils/threads.h>
24 
25 #include <android/graphics/Region.h>
26 #include <ui/Region.h>
27 
28 #include "android_hardware_input_InputWindowHandle.h"
29 #include "android_hardware_input_InputApplicationHandle.h"
30 #include "android_util_Binder.h"
31 
32 namespace android {
33 
34 struct WeakRefHandleField {
35     jfieldID handle;
36     jmethodID get;
37 };
38 
39 static struct {
40     jfieldID ptr;
41     jfieldID inputApplicationHandle;
42     jfieldID token;
43     jfieldID name;
44     jfieldID layoutParamsFlags;
45     jfieldID layoutParamsType;
46     jfieldID dispatchingTimeoutNanos;
47     jfieldID frameLeft;
48     jfieldID frameTop;
49     jfieldID frameRight;
50     jfieldID frameBottom;
51     jfieldID surfaceInset;
52     jfieldID scaleFactor;
53     jfieldID touchableRegion;
54     jfieldID visible;
55     jfieldID canReceiveKeys;
56     jfieldID hasFocus;
57     jfieldID hasWallpaper;
58     jfieldID paused;
59     jfieldID layer;
60     jfieldID ownerPid;
61     jfieldID ownerUid;
62     jfieldID inputFeatures;
63     jfieldID displayId;
64     jfieldID portalToDisplayId;
65     jfieldID replaceTouchableRegionWithCrop;
66     WeakRefHandleField touchableRegionCropHandle;
67 } gInputWindowHandleClassInfo;
68 
69 static Mutex gHandleMutex;
70 
71 
72 // --- NativeInputWindowHandle ---
73 
NativeInputWindowHandle(jweak objWeak)74 NativeInputWindowHandle::NativeInputWindowHandle(jweak objWeak) :
75         mObjWeak(objWeak) {
76 }
77 
~NativeInputWindowHandle()78 NativeInputWindowHandle::~NativeInputWindowHandle() {
79     JNIEnv* env = AndroidRuntime::getJNIEnv();
80     env->DeleteWeakGlobalRef(mObjWeak);
81 }
82 
getInputWindowHandleObjLocalRef(JNIEnv * env)83 jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
84     return env->NewLocalRef(mObjWeak);
85 }
86 
updateInfo()87 bool NativeInputWindowHandle::updateInfo() {
88     JNIEnv* env = AndroidRuntime::getJNIEnv();
89     jobject obj = env->NewLocalRef(mObjWeak);
90     if (!obj) {
91         releaseChannel();
92         return false;
93     }
94 
95     mInfo.touchableRegion.clear();
96 
97     jobject tokenObj = env->GetObjectField(obj, gInputWindowHandleClassInfo.token);
98     if (tokenObj) {
99         mInfo.token = ibinderForJavaObject(env, tokenObj);
100         env->DeleteLocalRef(tokenObj);
101     } else {
102         mInfo.token.clear();
103     }
104 
105     mInfo.name = getStringField(env, obj, gInputWindowHandleClassInfo.name, "<null>");
106 
107     mInfo.layoutParamsFlags = env->GetIntField(obj,
108             gInputWindowHandleClassInfo.layoutParamsFlags);
109     mInfo.layoutParamsType = env->GetIntField(obj,
110             gInputWindowHandleClassInfo.layoutParamsType);
111     mInfo.dispatchingTimeout = env->GetLongField(obj,
112             gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
113     mInfo.frameLeft = env->GetIntField(obj,
114             gInputWindowHandleClassInfo.frameLeft);
115     mInfo.frameTop = env->GetIntField(obj,
116             gInputWindowHandleClassInfo.frameTop);
117     mInfo.frameRight = env->GetIntField(obj,
118             gInputWindowHandleClassInfo.frameRight);
119     mInfo.frameBottom = env->GetIntField(obj,
120             gInputWindowHandleClassInfo.frameBottom);
121     mInfo.surfaceInset = env->GetIntField(obj,
122             gInputWindowHandleClassInfo.surfaceInset);
123     mInfo.globalScaleFactor = env->GetFloatField(obj,
124             gInputWindowHandleClassInfo.scaleFactor);
125 
126     jobject regionObj = env->GetObjectField(obj,
127             gInputWindowHandleClassInfo.touchableRegion);
128     if (regionObj) {
129         SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
130         for (SkRegion::Iterator it(*region); !it.done(); it.next()) {
131             const SkIRect& rect = it.rect();
132             mInfo.addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
133         }
134         env->DeleteLocalRef(regionObj);
135     }
136 
137     mInfo.visible = env->GetBooleanField(obj,
138             gInputWindowHandleClassInfo.visible);
139     mInfo.canReceiveKeys = env->GetBooleanField(obj,
140             gInputWindowHandleClassInfo.canReceiveKeys);
141     mInfo.hasFocus = env->GetBooleanField(obj,
142             gInputWindowHandleClassInfo.hasFocus);
143     mInfo.hasWallpaper = env->GetBooleanField(obj,
144             gInputWindowHandleClassInfo.hasWallpaper);
145     mInfo.paused = env->GetBooleanField(obj,
146             gInputWindowHandleClassInfo.paused);
147     mInfo.layer = env->GetIntField(obj,
148             gInputWindowHandleClassInfo.layer);
149     mInfo.ownerPid = env->GetIntField(obj,
150             gInputWindowHandleClassInfo.ownerPid);
151     mInfo.ownerUid = env->GetIntField(obj,
152             gInputWindowHandleClassInfo.ownerUid);
153     mInfo.inputFeatures = env->GetIntField(obj,
154             gInputWindowHandleClassInfo.inputFeatures);
155     mInfo.displayId = env->GetIntField(obj,
156             gInputWindowHandleClassInfo.displayId);
157     mInfo.portalToDisplayId = env->GetIntField(obj,
158             gInputWindowHandleClassInfo.portalToDisplayId);
159 
160     jobject inputApplicationHandleObj = env->GetObjectField(obj,
161             gInputWindowHandleClassInfo.inputApplicationHandle);
162     if (inputApplicationHandleObj) {
163         sp<InputApplicationHandle> inputApplicationHandle =
164             android_view_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
165         if (inputApplicationHandle != nullptr) {
166             inputApplicationHandle->updateInfo();
167             mInfo.applicationInfo = *(inputApplicationHandle->getInfo());
168         }
169         env->DeleteLocalRef(inputApplicationHandleObj);
170     }
171 
172     mInfo.replaceTouchableRegionWithCrop = env->GetBooleanField(obj,
173             gInputWindowHandleClassInfo.replaceTouchableRegionWithCrop);
174 
175     jobject handleObj = env->GetObjectField(obj,
176             gInputWindowHandleClassInfo.touchableRegionCropHandle.handle);
177     if (handleObj) {
178         // Promote java weak reference.
179         jobject strongHandleObj = env->CallObjectMethod(handleObj,
180                 gInputWindowHandleClassInfo.touchableRegionCropHandle.get);
181         if (strongHandleObj) {
182             mInfo.touchableRegionCropHandle = ibinderForJavaObject(env, strongHandleObj);
183             env->DeleteLocalRef(strongHandleObj);
184         } else {
185             mInfo.touchableRegionCropHandle.clear();
186         }
187         env->DeleteLocalRef(handleObj);
188     }
189 
190     env->DeleteLocalRef(obj);
191     return true;
192 }
193 
194 
195 // --- Global functions ---
196 
android_view_InputWindowHandle_getHandle(JNIEnv * env,jobject inputWindowHandleObj)197 sp<NativeInputWindowHandle> android_view_InputWindowHandle_getHandle(
198         JNIEnv* env, jobject inputWindowHandleObj) {
199     if (!inputWindowHandleObj) {
200         return NULL;
201     }
202 
203     AutoMutex _l(gHandleMutex);
204 
205     jlong ptr = env->GetLongField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr);
206     NativeInputWindowHandle* handle;
207     if (ptr) {
208         handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
209     } else {
210         jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
211         handle = new NativeInputWindowHandle(objWeak);
212         handle->incStrong((void*)android_view_InputWindowHandle_getHandle);
213         env->SetLongField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
214                 reinterpret_cast<jlong>(handle));
215     }
216     return handle;
217 }
218 
219 
220 // --- JNI ---
221 
android_view_InputWindowHandle_nativeDispose(JNIEnv * env,jobject obj)222 static void android_view_InputWindowHandle_nativeDispose(JNIEnv* env, jobject obj) {
223     AutoMutex _l(gHandleMutex);
224 
225     jlong ptr = env->GetLongField(obj, gInputWindowHandleClassInfo.ptr);
226     if (ptr) {
227         env->SetLongField(obj, gInputWindowHandleClassInfo.ptr, 0);
228 
229         NativeInputWindowHandle* handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
230         handle->decStrong((void*)android_view_InputWindowHandle_getHandle);
231     }
232 }
233 
234 
235 static const JNINativeMethod gInputWindowHandleMethods[] = {
236     /* name, signature, funcPtr */
237     { "nativeDispose", "()V",
238             (void*) android_view_InputWindowHandle_nativeDispose },
239 };
240 
241 #define FIND_CLASS(var, className) \
242         var = env->FindClass(className); \
243         LOG_FATAL_IF(! (var), "Unable to find class " className);
244 
245 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
246         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
247         LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
248 
249 #define GET_METHOD_ID(var, clazz, methodName, methodSignature) \
250         var = env->GetMethodID(clazz, methodName, methodSignature); \
251         LOG_FATAL_IF(! (var), "Unable to find method " methodName);
252 
register_android_view_InputWindowHandle(JNIEnv * env)253 int register_android_view_InputWindowHandle(JNIEnv* env) {
254     int res = jniRegisterNativeMethods(env, "android/view/InputWindowHandle",
255             gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
256     (void) res;  // Faked use when LOG_NDEBUG.
257     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
258 
259     jclass clazz;
260     FIND_CLASS(clazz, "android/view/InputWindowHandle");
261 
262     GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz,
263             "ptr", "J");
264 
265     GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle, clazz,
266             "inputApplicationHandle", "Landroid/view/InputApplicationHandle;");
267 
268     GET_FIELD_ID(gInputWindowHandleClassInfo.token, clazz,
269             "token", "Landroid/os/IBinder;");
270 
271     GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz,
272             "name", "Ljava/lang/String;");
273 
274     GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz,
275             "layoutParamsFlags", "I");
276 
277     GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz,
278             "layoutParamsType", "I");
279 
280     GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz,
281             "dispatchingTimeoutNanos", "J");
282 
283     GET_FIELD_ID(gInputWindowHandleClassInfo.frameLeft, clazz,
284             "frameLeft", "I");
285 
286     GET_FIELD_ID(gInputWindowHandleClassInfo.frameTop, clazz,
287             "frameTop", "I");
288 
289     GET_FIELD_ID(gInputWindowHandleClassInfo.frameRight, clazz,
290             "frameRight", "I");
291 
292     GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz,
293             "frameBottom", "I");
294 
295     GET_FIELD_ID(gInputWindowHandleClassInfo.surfaceInset, clazz,
296             "surfaceInset", "I");
297 
298     GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz,
299             "scaleFactor", "F");
300 
301     GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz,
302             "touchableRegion", "Landroid/graphics/Region;");
303 
304     GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz,
305             "visible", "Z");
306 
307     GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz,
308             "canReceiveKeys", "Z");
309 
310     GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz,
311             "hasFocus", "Z");
312 
313     GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz,
314             "hasWallpaper", "Z");
315 
316     GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
317             "paused", "Z");
318 
319     GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz,
320             "layer", "I");
321 
322     GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
323             "ownerPid", "I");
324 
325     GET_FIELD_ID(gInputWindowHandleClassInfo.ownerUid, clazz,
326             "ownerUid", "I");
327 
328     GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz,
329             "inputFeatures", "I");
330 
331     GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz,
332             "displayId", "I");
333 
334     GET_FIELD_ID(gInputWindowHandleClassInfo.portalToDisplayId, clazz,
335             "portalToDisplayId", "I");
336 
337     GET_FIELD_ID(gInputWindowHandleClassInfo.replaceTouchableRegionWithCrop, clazz,
338             "replaceTouchableRegionWithCrop", "Z");
339 
340     jclass weakRefClazz;
341     FIND_CLASS(weakRefClazz, "java/lang/ref/Reference");
342 
343     GET_METHOD_ID(gInputWindowHandleClassInfo.touchableRegionCropHandle.get, weakRefClazz,
344              "get", "()Ljava/lang/Object;")
345 
346     GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegionCropHandle.handle, clazz,
347             "touchableRegionCropHandle", "Ljava/lang/ref/WeakReference;");
348     return 0;
349 }
350 
351 } /* namespace android */
352