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