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