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