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 31namespace android { 32 33static 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 59static Mutex gHandleMutex; 60 61 62// --- NativeInputWindowHandle --- 63 64NativeInputWindowHandle::NativeInputWindowHandle( 65 const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) : 66 InputWindowHandle(inputApplicationHandle), 67 mObjWeak(objWeak) { 68} 69 70NativeInputWindowHandle::~NativeInputWindowHandle() { 71 JNIEnv* env = AndroidRuntime::getJNIEnv(); 72 env->DeleteWeakGlobalRef(mObjWeak); 73} 74 75jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) { 76 return env->NewLocalRef(mObjWeak); 77} 78 79bool 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 169sp<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 200static 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 213static 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 227int register_android_server_InputWindowHandle(JNIEnv* env) { 228 int res = jniRegisterNativeMethods(env, "com/android/server/input/InputWindowHandle", 229 gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods)); 230 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 231 232 jclass clazz; 233 FIND_CLASS(clazz, "com/android/server/input/InputWindowHandle"); 234 235 GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz, 236 "ptr", "J"); 237 238 GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle, 239 clazz, 240 "inputApplicationHandle", "Lcom/android/server/input/InputApplicationHandle;"); 241 242 GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz, 243 "inputChannel", "Landroid/view/InputChannel;"); 244 245 GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz, 246 "name", "Ljava/lang/String;"); 247 248 GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz, 249 "layoutParamsFlags", "I"); 250 251 GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz, 252 "layoutParamsType", "I"); 253 254 GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz, 255 "dispatchingTimeoutNanos", "J"); 256 257 GET_FIELD_ID(gInputWindowHandleClassInfo.frameLeft, clazz, 258 "frameLeft", "I"); 259 260 GET_FIELD_ID(gInputWindowHandleClassInfo.frameTop, clazz, 261 "frameTop", "I"); 262 263 GET_FIELD_ID(gInputWindowHandleClassInfo.frameRight, clazz, 264 "frameRight", "I"); 265 266 GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz, 267 "frameBottom", "I"); 268 269 GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz, 270 "scaleFactor", "F"); 271 272 GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz, 273 "touchableRegion", "Landroid/graphics/Region;"); 274 275 GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz, 276 "visible", "Z"); 277 278 GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz, 279 "canReceiveKeys", "Z"); 280 281 GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz, 282 "hasFocus", "Z"); 283 284 GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz, 285 "hasWallpaper", "Z"); 286 287 GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz, 288 "paused", "Z"); 289 290 GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz, 291 "layer", "I"); 292 293 GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz, 294 "ownerPid", "I"); 295 296 GET_FIELD_ID(gInputWindowHandleClassInfo.ownerUid, clazz, 297 "ownerUid", "I"); 298 299 GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz, 300 "inputFeatures", "I"); 301 302 GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz, 303 "displayId", "I"); 304 return 0; 305} 306 307} /* namespace android */ 308