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