com_android_server_fingerprint_FingerprintService.cpp revision ebbf205bc6e8292f74d8fc4652c70274a445f907
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#include <inttypes.h> 21 22#include <android_runtime/AndroidRuntime.h> 23#include <android_runtime/Log.h> 24#include <android_os_MessageQueue.h> 25#include <hardware/hardware.h> 26#include <hardware/fingerprint.h> 27#include <utils/Log.h> 28#include <utils/Looper.h> 29#include "core_jni_helpers.h" 30 31namespace android { 32 33static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 0); 34 35static const char* FINGERPRINT_SERVICE = "com/android/server/fingerprint/FingerprintService"; 36static struct { 37 jclass clazz; 38 jmethodID notify; 39} gFingerprintServiceClassInfo; 40 41static struct { 42 fingerprint_module_t const* module; 43 fingerprint_device_t *device; 44} gContext; 45 46static sp<Looper> gLooper; 47static jobject gCallback; 48 49class CallbackHandler : public MessageHandler { 50 int type; 51 int arg1, arg2, arg3; 52public: 53 CallbackHandler(int type, int arg1, int arg2, int arg3) 54 : type(type), arg1(arg1), arg2(arg2), arg3(arg3) { } 55 56 virtual void handleMessage(const Message& message) { 57 //ALOG(LOG_VERBOSE, LOG_TAG, "hal_notify(msg=%d, arg1=%d, arg2=%d)\n", msg.type, arg1, arg2); 58 JNIEnv* env = AndroidRuntime::getJNIEnv(); 59 env->CallVoidMethod(gCallback, gFingerprintServiceClassInfo.notify, type, arg1, arg2, arg3); 60 } 61}; 62 63// Called by the HAL to notify us of fingerprint events 64static void hal_notify_callback(fingerprint_msg_t msg) { 65 uint32_t arg1 = 0; 66 uint32_t arg2 = 0; 67 uint32_t arg3 = 0; 68 switch (msg.type) { 69 case FINGERPRINT_ERROR: 70 arg1 = msg.data.error; 71 break; 72 case FINGERPRINT_ACQUIRED: 73 arg1 = msg.data.acquired.acquired_info; 74 break; 75 case FINGERPRINT_PROCESSED: 76 arg1 = msg.data.processed.finger.fid; 77 arg2 = msg.data.processed.finger.gid; 78 break; 79 case FINGERPRINT_TEMPLATE_ENROLLING: 80 arg1 = msg.data.enroll.finger.fid; 81 arg2 = msg.data.enroll.finger.gid; 82 arg3 = msg.data.enroll.samples_remaining; 83 break; 84 case FINGERPRINT_TEMPLATE_REMOVED: 85 arg1 = msg.data.removed.finger.fid; 86 arg2 = msg.data.removed.finger.gid; 87 break; 88 default: 89 ALOGE("fingerprint: invalid msg: %d", msg.type); 90 return; 91 } 92 // This call potentially comes in on a thread not owned by us. Hand it off to our 93 // looper so it runs on our thread when calling back to FingerprintService. 94 // CallbackHandler object is reference-counted, so no cleanup necessary. 95 gLooper->sendMessage(new CallbackHandler(msg.type, arg1, arg2, arg3), Message()); 96} 97 98static void nativeInit(JNIEnv *env, jobject clazz, jobject mQueue, jobject callbackObj) { 99 ALOG(LOG_VERBOSE, LOG_TAG, "nativeInit()\n"); 100 gCallback = MakeGlobalRefOrDie(env, callbackObj); 101 gLooper = android_os_MessageQueue_getMessageQueue(env, mQueue)->getLooper(); 102} 103 104static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout, jint groupId) { 105 ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll(gid=%d, timeout=%d)\n", groupId, timeout); 106 int ret = gContext.device->enroll(gContext.device, groupId, timeout); 107 return reinterpret_cast<jint>(ret); 108} 109 110static jint nativeAuthenticate(JNIEnv* env, jobject clazz, jlong sessionId, jint groupId) { 111 ALOG(LOG_VERBOSE, LOG_TAG, "nativeAuthenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId); 112 int ret = gContext.device->authenticate(gContext.device, sessionId, groupId); 113 return reinterpret_cast<jint>(ret); 114} 115 116static jint nativeEnrollCancel(JNIEnv* env, jobject clazz) { 117 ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnrollCancel()\n"); 118 int ret = gContext.device->enroll_cancel(gContext.device); 119 return reinterpret_cast<jint>(ret); 120} 121 122static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerId, jint groupId) { 123 ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(fid=%d, gid=%d)\n", fingerId, groupId); 124 fingerprint_finger_id_t finger; 125 finger.fid = fingerId; 126 finger.gid = groupId; 127 int ret = gContext.device->remove(gContext.device, finger); 128 return reinterpret_cast<jint>(ret); 129} 130 131static jint nativeOpenHal(JNIEnv* env, jobject clazz) { 132 ALOG(LOG_VERBOSE, LOG_TAG, "nativeOpenHal()\n"); 133 int err; 134 const hw_module_t *hw_module = NULL; 135 if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) { 136 ALOGE("Can't open fingerprint HW Module, error: %d", err); 137 return 0; 138 } 139 if (NULL == hw_module) { 140 ALOGE("No valid fingerprint module"); 141 return 0; 142 } 143 144 gContext.module = reinterpret_cast<const fingerprint_module_t*>(hw_module); 145 146 if (gContext.module->common.methods->open == NULL) { 147 ALOGE("No valid open method"); 148 return 0; 149 } 150 151 hw_device_t *device = NULL; 152 153 if (0 != (err = gContext.module->common.methods->open(hw_module, NULL, &device))) { 154 ALOGE("Can't open fingerprint methods, error: %d", err); 155 return 0; 156 } 157 158 if (kVersion != device->version) { 159 ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version); 160 // return 0; // FIXME 161 } 162 163 gContext.device = reinterpret_cast<fingerprint_device_t*>(device); 164 err = gContext.device->set_notify(gContext.device, hal_notify_callback); 165 if (err < 0) { 166 ALOGE("Failed in call to set_notify(), err=%d", err); 167 return 0; 168 } 169 170 // Sanity check - remove 171 if (gContext.device->notify != hal_notify_callback) { 172 ALOGE("NOTIFY not set properly: %p != %p", gContext.device->notify, hal_notify_callback); 173 } 174 175 ALOG(LOG_VERBOSE, LOG_TAG, "fingerprint HAL successfully initialized"); 176 return reinterpret_cast<jlong>(gContext.device); 177} 178 179static jint nativeCloseHal(JNIEnv* env, jobject clazz) { 180 return -ENOSYS; // TODO 181} 182 183// ---------------------------------------------------------------------------- 184 185// TODO: clean up void methods 186static const JNINativeMethod g_methods[] = { 187 { "nativeAuthenticate", "(JI)I", (void*)nativeAuthenticate }, 188 { "nativeEnroll", "(II)I", (void*)nativeEnroll }, 189 { "nativeEnrollCancel", "()I", (void*)nativeEnrollCancel }, 190 { "nativeRemove", "(II)I", (void*)nativeRemove }, 191 { "nativeOpenHal", "()I", (void*)nativeOpenHal }, 192 { "nativeCloseHal", "()I", (void*)nativeCloseHal }, 193 { "nativeInit","(Landroid/os/MessageQueue;" 194 "Lcom/android/server/fingerprint/FingerprintService;)V", (void*)nativeInit } 195}; 196 197int register_android_server_fingerprint_FingerprintService(JNIEnv* env) { 198 jclass clazz = FindClassOrDie(env, FINGERPRINT_SERVICE); 199 gFingerprintServiceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); 200 gFingerprintServiceClassInfo.notify = 201 GetMethodIDOrDie(env, gFingerprintServiceClassInfo.clazz,"notify", "(IIII)V"); 202 int result = RegisterMethodsOrDie(env, FINGERPRINT_SERVICE, g_methods, NELEM(g_methods)); 203 ALOG(LOG_VERBOSE, LOG_TAG, "FingerprintManager JNI ready.\n"); 204 return result; 205} 206 207} // namespace android 208