12352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown/*
22352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * Copyright (C) 2011 The Android Open Source Project
32352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown *
42352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
52352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * you may not use this file except in compliance with the License.
62352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * You may obtain a copy of the License at
72352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown *
82352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
92352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown *
102352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * Unless required by applicable law or agreed to in writing, software
112352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
122352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * See the License for the specific language governing permissions and
142352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown * limitations under the License.
152352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown */
162352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
172352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown#define LOG_TAG "PointerIcon-JNI"
182352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
192279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/JNIHelp.h>
202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
212352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown#include "android_view_PointerIcon.h"
222352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
232352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown#include <android_runtime/AndroidRuntime.h>
2487eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include <android_runtime/Log.h>
252352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown#include <utils/Log.h>
262352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown#include <android/graphics/GraphicsJNI.h>
272279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedLocalRef.h>
282352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
29987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe#include "core_jni_helpers.h"
30987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe
312352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownnamespace android {
322352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
332352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownstatic struct {
342352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jclass clazz;
35f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright    jfieldID mType;
362352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jfieldID mBitmap;
372352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jfieldID mHotSpotX;
382352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jfieldID mHotSpotY;
39808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai    jfieldID mBitmapFrames;
40808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai    jfieldID mDurationPerFrame;
412352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jmethodID getSystemIcon;
422352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jmethodID load;
432352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown} gPointerIconClassInfo;
442352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
452352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
462352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown// --- Global Functions ---
472352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
482352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownjobject android_view_PointerIcon_getSystemIcon(JNIEnv* env, jobject contextObj, int32_t style) {
492352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jobject pointerIconObj = env->CallStaticObjectMethod(gPointerIconClassInfo.clazz,
502352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            gPointerIconClassInfo.getSystemIcon, contextObj, style);
512352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (env->ExceptionCheck()) {
528564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("An exception occurred while getting a pointer icon with style %d.", style);
532352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        LOGW_EX(env);
542352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        env->ExceptionClear();
552352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return NULL;
562352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    return pointerIconObj;
582352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
592352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
602352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownstatus_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobject contextObj,
612352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        PointerIcon* outPointerIcon) {
622352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    outPointerIcon->reset();
632352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
642352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (!pointerIconObj) {
652352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return OK;
662352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
672352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
68d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    ScopedLocalRef<jobject> loadedPointerIconObj(env, env->CallObjectMethod(pointerIconObj,
69d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai            gPointerIconClassInfo.load, contextObj));
70d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    if (env->ExceptionCheck() || !loadedPointerIconObj.get()) {
718564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("An exception occurred while loading a pointer icon.");
722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        LOGW_EX(env);
732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        env->ExceptionClear();
742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return UNKNOWN_ERROR;
752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
76d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    return android_view_PointerIcon_getLoadedIcon(env, loadedPointerIconObj.get(), outPointerIcon);
77d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai}
782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
79d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukaistatus_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj,
80d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        PointerIcon* outPointerIcon) {
8135068079c833b5ea508c378701b159b99ee39279Michael Wright    if (!pointerIconObj) {
8235068079c833b5ea508c378701b159b99ee39279Michael Wright        return BAD_VALUE;
8335068079c833b5ea508c378701b159b99ee39279Michael Wright    }
84f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright    outPointerIcon->style = env->GetIntField(pointerIconObj, gPointerIconClassInfo.mType);
85d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    outPointerIcon->hotSpotX = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotX);
86d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    outPointerIcon->hotSpotY = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotY);
87d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai
88d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    ScopedLocalRef<jobject> bitmapObj(
89d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai            env, env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmap));
90d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    if (bitmapObj.get()) {
91d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmap));
922352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
932352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
94808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai    ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>(
95d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai            env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmapFrames)));
96808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai    if (bitmapFramesObj.get()) {
97808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai        outPointerIcon->durationPerFrame = env->GetIntField(
98d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai                pointerIconObj, gPointerIconClassInfo.mDurationPerFrame);
99808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai        jsize size = env->GetArrayLength(bitmapFramesObj.get());
100808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai        outPointerIcon->bitmapFrames.resize(size);
101808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai        for (jsize i = 0; i < size; ++i) {
102808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai            ScopedLocalRef<jobject> bitmapObj(env, env->GetObjectArrayElement(bitmapFramesObj.get(), i));
103808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai            GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmapFrames[i]));
104808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai        }
105808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai    }
106808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai
1072352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    return OK;
1082352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
1092352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1102352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownstatus_t android_view_PointerIcon_loadSystemIcon(JNIEnv* env, jobject contextObj,
1112352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        int32_t style, PointerIcon* outPointerIcon) {
1122352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    jobject pointerIconObj = android_view_PointerIcon_getSystemIcon(env, contextObj, style);
1132352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (!pointerIconObj) {
1142352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        outPointerIcon->reset();
1152352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return UNKNOWN_ERROR;
1162352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
1172352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1182352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    status_t status = android_view_PointerIcon_load(env, pointerIconObj,
1192352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            contextObj, outPointerIcon);
1202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    env->DeleteLocalRef(pointerIconObj);
1212352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    return status;
1222352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
1232352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1242352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1252352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown// --- JNI Registration ---
1262352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1272352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownint register_android_view_PointerIcon(JNIEnv* env) {
128987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    jclass clazz = FindClassOrDie(env, "android/view/PointerIcon");
129987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gPointerIconClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
1302352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
131987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gPointerIconClassInfo.mBitmap = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
1322352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "mBitmap", "Landroid/graphics/Bitmap;");
1332352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
134f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright    gPointerIconClassInfo.mType = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
135f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright            "mType", "I");
1362352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
137987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gPointerIconClassInfo.mHotSpotX = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
1382352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "mHotSpotX", "F");
1392352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
140987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gPointerIconClassInfo.mHotSpotY = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
1412352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "mHotSpotY", "F");
1422352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
143808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai    gPointerIconClassInfo.mBitmapFrames = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
144808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai            "mBitmapFrames", "[Landroid/graphics/Bitmap;");
145808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai
146808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai    gPointerIconClassInfo.mDurationPerFrame = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
147808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai            "mDurationPerFrame", "I");
148808196f139e93395f1f331f6c7e92ddd66c05979Jun Mukai
149987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gPointerIconClassInfo.getSystemIcon = GetStaticMethodIDOrDie(env, gPointerIconClassInfo.clazz,
1502352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "getSystemIcon", "(Landroid/content/Context;I)Landroid/view/PointerIcon;");
1512352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
152987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gPointerIconClassInfo.load = GetMethodIDOrDie(env, gPointerIconClassInfo.clazz,
1532352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "load", "(Landroid/content/Context;)Landroid/view/PointerIcon;");
1542352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1552352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    return 0;
1562352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
1572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1582352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown} // namespace android
159