Home | History | Annotate | Download | only in jni
      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