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 "JNIHelp.h" 20 #include "jni.h" 21 #include <android_runtime/AndroidRuntime.h> 22 #include <utils/threads.h> 23 24 #include <android_view_InputChannel.h> 25 #include <android/graphics/Region.h> 26 27 #include "com_android_server_input_InputWindowHandle.h" 28 #include "com_android_server_input_InputApplicationHandle.h" 29 30 namespace android { 31 32 static struct { 33 jfieldID ptr; 34 jfieldID inputApplicationHandle; 35 jfieldID inputChannel; 36 jfieldID name; 37 jfieldID layoutParamsFlags; 38 jfieldID layoutParamsType; 39 jfieldID dispatchingTimeoutNanos; 40 jfieldID frameLeft; 41 jfieldID frameTop; 42 jfieldID frameRight; 43 jfieldID frameBottom; 44 jfieldID scaleFactor; 45 jfieldID touchableRegion; 46 jfieldID visible; 47 jfieldID canReceiveKeys; 48 jfieldID hasFocus; 49 jfieldID hasWallpaper; 50 jfieldID paused; 51 jfieldID layer; 52 jfieldID ownerPid; 53 jfieldID ownerUid; 54 jfieldID inputFeatures; 55 jfieldID displayId; 56 } gInputWindowHandleClassInfo; 57 58 static Mutex gHandleMutex; 59 60 61 // --- NativeInputWindowHandle --- 62 63 NativeInputWindowHandle::NativeInputWindowHandle( 64 const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) : 65 InputWindowHandle(inputApplicationHandle), 66 mObjWeak(objWeak) { 67 } 68 69 NativeInputWindowHandle::~NativeInputWindowHandle() { 70 JNIEnv* env = AndroidRuntime::getJNIEnv(); 71 env->DeleteWeakGlobalRef(mObjWeak); 72 } 73 74 jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) { 75 return env->NewLocalRef(mObjWeak); 76 } 77 78 bool NativeInputWindowHandle::updateInfo() { 79 JNIEnv* env = AndroidRuntime::getJNIEnv(); 80 jobject obj = env->NewLocalRef(mObjWeak); 81 if (!obj) { 82 releaseInfo(); 83 return false; 84 } 85 86 if (!mInfo) { 87 mInfo = new InputWindowInfo(); 88 } 89 90 jobject inputChannelObj = env->GetObjectField(obj, 91 gInputWindowHandleClassInfo.inputChannel); 92 if (inputChannelObj) { 93 mInfo->inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj); 94 env->DeleteLocalRef(inputChannelObj); 95 } else { 96 mInfo->inputChannel.clear(); 97 } 98 99 jstring nameObj = jstring(env->GetObjectField(obj, 100 gInputWindowHandleClassInfo.name)); 101 if (nameObj) { 102 const char* nameStr = env->GetStringUTFChars(nameObj, NULL); 103 mInfo->name.setTo(nameStr); 104 env->ReleaseStringUTFChars(nameObj, nameStr); 105 env->DeleteLocalRef(nameObj); 106 } else { 107 mInfo->name.setTo("<null>"); 108 } 109 110 mInfo->layoutParamsFlags = env->GetIntField(obj, 111 gInputWindowHandleClassInfo.layoutParamsFlags); 112 mInfo->layoutParamsType = env->GetIntField(obj, 113 gInputWindowHandleClassInfo.layoutParamsType); 114 mInfo->dispatchingTimeout = env->GetLongField(obj, 115 gInputWindowHandleClassInfo.dispatchingTimeoutNanos); 116 mInfo->frameLeft = env->GetIntField(obj, 117 gInputWindowHandleClassInfo.frameLeft); 118 mInfo->frameTop = env->GetIntField(obj, 119 gInputWindowHandleClassInfo.frameTop); 120 mInfo->frameRight = env->GetIntField(obj, 121 gInputWindowHandleClassInfo.frameRight); 122 mInfo->frameBottom = env->GetIntField(obj, 123 gInputWindowHandleClassInfo.frameBottom); 124 mInfo->scaleFactor = env->GetFloatField(obj, 125 gInputWindowHandleClassInfo.scaleFactor); 126 127 jobject regionObj = env->GetObjectField(obj, 128 gInputWindowHandleClassInfo.touchableRegion); 129 if (regionObj) { 130 SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); 131 mInfo->touchableRegion.set(*region); 132 env->DeleteLocalRef(regionObj); 133 } else { 134 mInfo->touchableRegion.setEmpty(); 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 158 env->DeleteLocalRef(obj); 159 return true; 160 } 161 162 163 // --- Global functions --- 164 165 sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle( 166 JNIEnv* env, jobject inputWindowHandleObj) { 167 if (!inputWindowHandleObj) { 168 return NULL; 169 } 170 171 AutoMutex _l(gHandleMutex); 172 173 int ptr = env->GetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr); 174 NativeInputWindowHandle* handle; 175 if (ptr) { 176 handle = reinterpret_cast<NativeInputWindowHandle*>(ptr); 177 } else { 178 jobject inputApplicationHandleObj = env->GetObjectField(inputWindowHandleObj, 179 gInputWindowHandleClassInfo.inputApplicationHandle); 180 sp<InputApplicationHandle> inputApplicationHandle = 181 android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj); 182 env->DeleteLocalRef(inputApplicationHandleObj); 183 184 jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj); 185 handle = new NativeInputWindowHandle(inputApplicationHandle, objWeak); 186 handle->incStrong((void*)android_server_InputWindowHandle_getHandle); 187 env->SetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr, 188 reinterpret_cast<int>(handle)); 189 } 190 return handle; 191 } 192 193 194 // --- JNI --- 195 196 static void android_server_InputWindowHandle_nativeDispose(JNIEnv* env, jobject obj) { 197 AutoMutex _l(gHandleMutex); 198 199 int ptr = env->GetIntField(obj, gInputWindowHandleClassInfo.ptr); 200 if (ptr) { 201 env->SetIntField(obj, gInputWindowHandleClassInfo.ptr, 0); 202 203 NativeInputWindowHandle* handle = reinterpret_cast<NativeInputWindowHandle*>(ptr); 204 handle->decStrong((void*)android_server_InputWindowHandle_getHandle); 205 } 206 } 207 208 209 static JNINativeMethod gInputWindowHandleMethods[] = { 210 /* name, signature, funcPtr */ 211 { "nativeDispose", "()V", 212 (void*) android_server_InputWindowHandle_nativeDispose }, 213 }; 214 215 #define FIND_CLASS(var, className) \ 216 var = env->FindClass(className); \ 217 LOG_FATAL_IF(! var, "Unable to find class " className); 218 219 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 220 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 221 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 222 223 int register_android_server_InputWindowHandle(JNIEnv* env) { 224 int res = jniRegisterNativeMethods(env, "com/android/server/input/InputWindowHandle", 225 gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods)); 226 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 227 228 jclass clazz; 229 FIND_CLASS(clazz, "com/android/server/input/InputWindowHandle"); 230 231 GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz, 232 "ptr", "I"); 233 234 GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle, 235 clazz, 236 "inputApplicationHandle", "Lcom/android/server/input/InputApplicationHandle;"); 237 238 GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz, 239 "inputChannel", "Landroid/view/InputChannel;"); 240 241 GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz, 242 "name", "Ljava/lang/String;"); 243 244 GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz, 245 "layoutParamsFlags", "I"); 246 247 GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz, 248 "layoutParamsType", "I"); 249 250 GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz, 251 "dispatchingTimeoutNanos", "J"); 252 253 GET_FIELD_ID(gInputWindowHandleClassInfo.frameLeft, clazz, 254 "frameLeft", "I"); 255 256 GET_FIELD_ID(gInputWindowHandleClassInfo.frameTop, clazz, 257 "frameTop", "I"); 258 259 GET_FIELD_ID(gInputWindowHandleClassInfo.frameRight, clazz, 260 "frameRight", "I"); 261 262 GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz, 263 "frameBottom", "I"); 264 265 GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz, 266 "scaleFactor", "F"); 267 268 GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz, 269 "touchableRegion", "Landroid/graphics/Region;"); 270 271 GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz, 272 "visible", "Z"); 273 274 GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz, 275 "canReceiveKeys", "Z"); 276 277 GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz, 278 "hasFocus", "Z"); 279 280 GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz, 281 "hasWallpaper", "Z"); 282 283 GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz, 284 "paused", "Z"); 285 286 GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz, 287 "layer", "I"); 288 289 GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz, 290 "ownerPid", "I"); 291 292 GET_FIELD_ID(gInputWindowHandleClassInfo.ownerUid, clazz, 293 "ownerUid", "I"); 294 295 GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz, 296 "inputFeatures", "I"); 297 298 GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz, 299 "displayId", "I"); 300 return 0; 301 } 302 303 } /* namespace android */ 304