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