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_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