OSDN Git Service

am a63f81ec: am e15773be: Merge "docs: Android TV publishing requirements" into klp...
[android-x86/frameworks-base.git] / core / jni / android_server_FingerprintManager.cpp
1 /*
2  * Copyright (C) 2014 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 "Fingerprint-JNI"
18
19 #include "JNIHelp.h"
20
21 #include <android_runtime/AndroidRuntime.h>
22 #include <android_runtime/Log.h>
23 #include <hardware/hardware.h>
24 #include <hardware/fingerprint.h>
25 #include <utils/Log.h>
26
27 #define FIND_CLASS(var, className) \
28         var = env->FindClass(className); \
29         LOG_FATAL_IF(! var, "Unable to find class " className); \
30         var = jclass(env->NewGlobalRef(var));
31
32 #define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
33         var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
34         LOG_FATAL_IF(! var, "Unable to find static method" methodName);
35
36 #define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
37         var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
38         LOG_FATAL_IF(! var, "Unable to find method" methodName);
39
40 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
41         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
42         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
43
44 namespace android {
45
46 static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(1, 0);
47
48 static const char* FINGERPRINT_SERVICE = "com/android/server/fingerprint/FingerprintService";
49 static struct {
50     jclass clazz;
51     jmethodID notify;
52     jobject callbackObject;
53 } gFingerprintServiceClassInfo;
54
55 static struct {
56     fingerprint_module_t const* module;
57     fingerprint_device_t *device;
58 } gContext;
59
60 // Called by the HAL to notify us of fingerprint events
61 static void hal_notify_callback(fingerprint_msg_t msg) {
62     uint32_t arg1 = 0;
63     uint32_t arg2 = 0;
64     uint32_t arg3 = 0; // TODO
65     switch (msg.type) {
66         case FINGERPRINT_ERROR:
67             arg1 = msg.data.error;
68             break;
69         case FINGERPRINT_ACQUIRED:
70             arg1 = msg.data.acquired.acquired_info;
71             break;
72         case FINGERPRINT_PROCESSED:
73             arg1 = msg.data.processed.id;
74             break;
75         case FINGERPRINT_TEMPLATE_ENROLLING:
76             arg1 = msg.data.enroll.id;
77             arg2 = msg.data.enroll.samples_remaining;
78             arg3 = msg.data.enroll.data_collected_bmp;
79             break;
80         case FINGERPRINT_TEMPLATE_REMOVED:
81             arg1 = msg.data.removed.id;
82             break;
83         default:
84             ALOGE("fingerprint: invalid msg: %d", msg.type);
85             return;
86     }
87     //ALOG(LOG_VERBOSE, LOG_TAG, "hal_notify(msg=%d, arg1=%d, arg2=%d)\n", msg.type, arg1, arg2);
88
89         // TODO: fix gross hack to attach JNI to calling thread
90     JNIEnv* env = AndroidRuntime::getJNIEnv();
91     if (env == NULL) {
92         JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
93         JavaVM* vm = AndroidRuntime::getJavaVM();
94         int result = vm->AttachCurrentThread(&env, (void*) &args);
95         if (result != JNI_OK) {
96             ALOGE("Can't call JNI method: attach failed: %#x", result);
97             return;
98         }
99     }
100     env->CallVoidMethod(gFingerprintServiceClassInfo.callbackObject,
101             gFingerprintServiceClassInfo.notify, msg.type, arg1, arg2);
102 }
103
104 static void nativeInit(JNIEnv *env, jobject clazz, jobject callbackObj) {
105     ALOG(LOG_VERBOSE, LOG_TAG, "nativeInit()\n");
106     FIND_CLASS(gFingerprintServiceClassInfo.clazz, FINGERPRINT_SERVICE);
107     GET_METHOD_ID(gFingerprintServiceClassInfo.notify, gFingerprintServiceClassInfo.clazz,
108            "notify", "(III)V");
109     gFingerprintServiceClassInfo.callbackObject = env->NewGlobalRef(callbackObj);
110 }
111
112 static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) {
113     ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll()\n");
114     int ret = gContext.device->enroll(gContext.device, timeout);
115     return reinterpret_cast<jint>(ret);
116 }
117
118 static jint nativeEnrollCancel(JNIEnv* env, jobject clazz) {
119     ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnrollCancel()\n");
120     int ret = gContext.device->enroll_cancel(gContext.device);
121     return reinterpret_cast<jint>(ret);
122 }
123
124 static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) {
125     ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(%d)\n", fingerprintId);
126     int ret = gContext.device->remove(gContext.device, fingerprintId);
127     return reinterpret_cast<jint>(ret);
128 }
129
130 static jint nativeOpenHal(JNIEnv* env, jobject clazz) {
131     ALOG(LOG_VERBOSE, LOG_TAG, "nativeOpenHal()\n");
132     int err;
133     const hw_module_t *hw_module = NULL;
134     if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) {
135         ALOGE("Can't open fingerprint HW Module, error: %d", err);
136         return 0;
137     }
138     if (NULL == hw_module) {
139         ALOGE("No valid fingerprint module");
140         return 0;
141     }
142
143     gContext.module = reinterpret_cast<const fingerprint_module_t*>(hw_module);
144
145     if (gContext.module->common.methods->open == NULL) {
146         ALOGE("No valid open method");
147         return 0;
148     }
149
150     hw_device_t *device = NULL;
151
152     if (0 != (err = gContext.module->common.methods->open(hw_module, NULL, &device))) {
153         ALOGE("Can't open fingerprint methods, error: %d", err);
154         return 0;
155     }
156
157     if (kVersion != device->version) {
158         ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
159         // return 0; // FIXME
160     }
161
162     gContext.device = reinterpret_cast<fingerprint_device_t*>(device);
163     err = gContext.device->set_notify(gContext.device, hal_notify_callback);
164     if (err < 0) {
165         ALOGE("Failed in call to set_notify(), err=%d", err);
166         return 0;
167     }
168
169     // Sanity check - remove
170     if (gContext.device->notify != hal_notify_callback) {
171         ALOGE("NOTIFY not set properly: %p != %p", gContext.device->notify, hal_notify_callback);
172     }
173
174     ALOG(LOG_VERBOSE, LOG_TAG, "fingerprint HAL successfully initialized");
175     return reinterpret_cast<jlong>(gContext.device);
176 }
177
178 static jint nativeCloseHal(JNIEnv* env, jobject clazz) {
179     return -ENOSYS; // TODO
180 }
181
182 // ----------------------------------------------------------------------------
183
184 // TODO: clean up void methods
185 static const JNINativeMethod g_methods[] = {
186     { "nativeEnroll", "(I)I", (void*)nativeEnroll },
187     { "nativeEnrollCancel", "()I", (void*)nativeEnroll },
188     { "nativeRemove", "(I)I", (void*)nativeRemove },
189     { "nativeOpenHal", "()I", (void*)nativeOpenHal },
190     { "nativeCloseHal", "()I", (void*)nativeCloseHal },
191     { "nativeInit", "(Lcom/android/server/fingerprint/FingerprintService;)V", (void*)nativeInit }
192 };
193
194 int register_android_server_fingerprint_FingerprintService(JNIEnv* env) {
195     FIND_CLASS(gFingerprintServiceClassInfo.clazz, FINGERPRINT_SERVICE);
196     GET_METHOD_ID(gFingerprintServiceClassInfo.notify, gFingerprintServiceClassInfo.clazz, "notify",
197             "(III)V");
198     int result = AndroidRuntime::registerNativeMethods(
199         env, FINGERPRINT_SERVICE, g_methods, NELEM(g_methods));
200     ALOG(LOG_VERBOSE, LOG_TAG, "FingerprintManager JNI ready.\n");
201     return result;
202 }
203
204 } // namespace android