com_android_server_fingerprint_FingerprintService.cpp revision 205bbc40b4a3046ca3dba256535f0322f5b336e9
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 <binder/IServiceManager.h> 26#include <utils/String16.h> 27#include <utils/Looper.h> 28#include <keystore/IKeystoreService.h> 29 30#include <hardware/hardware.h> 31#include <hardware/fingerprint.h> 32#include <hardware/hw_auth_token.h> 33 34#include <utils/Log.h> 35#include "core_jni_helpers.h" 36 37 38namespace android { 39 40static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 0); 41 42static const char* FINGERPRINT_SERVICE = "com/android/server/fingerprint/FingerprintService"; 43static struct { 44 jclass clazz; 45 jmethodID notify; 46} gFingerprintServiceClassInfo; 47 48static struct { 49 fingerprint_module_t const* module; 50 fingerprint_device_t *device; 51} gContext; 52 53static sp<Looper> gLooper; 54static jobject gCallback; 55 56class CallbackHandler : public MessageHandler { 57 int type; 58 int arg1, arg2, arg3; 59public: 60 CallbackHandler(int type, int arg1, int arg2, int arg3) 61 : type(type), arg1(arg1), arg2(arg2), arg3(arg3) { } 62 63 virtual void handleMessage(const Message& message) { 64 //ALOG(LOG_VERBOSE, LOG_TAG, "hal_notify(msg=%d, arg1=%d, arg2=%d)\n", msg.type, arg1, arg2); 65 JNIEnv* env = AndroidRuntime::getJNIEnv(); 66 env->CallVoidMethod(gCallback, gFingerprintServiceClassInfo.notify, type, arg1, arg2, arg3); 67 } 68}; 69 70static void notifyKeystore(uint8_t *auth_token, size_t auth_token_length) { 71 if (auth_token != NULL && auth_token_length > 0) { 72 // TODO: cache service? 73 sp<IServiceManager> sm = defaultServiceManager(); 74 sp<IBinder> binder = sm->getService(String16("android.security.keystore")); 75 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder); 76 if (service != NULL) { 77 if (service->addAuthToken(auth_token, auth_token_length) != NO_ERROR) { 78 ALOGE("Falure sending auth token to KeyStore"); 79 } 80 } else { 81 ALOGE("Unable to communicate with KeyStore"); 82 } 83 } 84} 85 86// Called by the HAL to notify us of fingerprint events 87static void hal_notify_callback(fingerprint_msg_t msg) { 88 uint32_t arg1 = 0; 89 uint32_t arg2 = 0; 90 uint32_t arg3 = 0; 91 switch (msg.type) { 92 case FINGERPRINT_ERROR: 93 arg1 = msg.data.error; 94 break; 95 case FINGERPRINT_ACQUIRED: 96 arg1 = msg.data.acquired.acquired_info; 97 break; 98 case FINGERPRINT_AUTHENTICATED: 99 arg1 = msg.data.authenticated.finger.fid; 100 arg2 = msg.data.authenticated.finger.gid; 101 if (arg1 != 0) { 102 notifyKeystore(reinterpret_cast<uint8_t *>(&msg.data.authenticated.hat), 103 sizeof(msg.data.authenticated.hat)); 104 } 105 break; 106 case FINGERPRINT_TEMPLATE_ENROLLING: 107 arg1 = msg.data.enroll.finger.fid; 108 arg2 = msg.data.enroll.finger.gid; 109 arg3 = msg.data.enroll.samples_remaining; 110 break; 111 case FINGERPRINT_TEMPLATE_REMOVED: 112 arg1 = msg.data.removed.finger.fid; 113 arg2 = msg.data.removed.finger.gid; 114 break; 115 default: 116 ALOGE("fingerprint: invalid msg: %d", msg.type); 117 return; 118 } 119 // This call potentially comes in on a thread not owned by us. Hand it off to our 120 // looper so it runs on our thread when calling back to FingerprintService. 121 // CallbackHandler object is reference-counted, so no cleanup necessary. 122 gLooper->sendMessage(new CallbackHandler(msg.type, arg1, arg2, arg3), Message()); 123} 124 125static void nativeInit(JNIEnv *env, jobject clazz, jobject mQueue, jobject callbackObj) { 126 ALOG(LOG_VERBOSE, LOG_TAG, "nativeInit()\n"); 127 gCallback = MakeGlobalRefOrDie(env, callbackObj); 128 gLooper = android_os_MessageQueue_getMessageQueue(env, mQueue)->getLooper(); 129} 130 131static jint nativeEnroll(JNIEnv* env, jobject clazz, jint groupId, jint timeout) { 132 hw_auth_token_t *hat = NULL; // This is here as a placeholder, 133 // please figure out your favorite way to send the hat struct through JNI 134 ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll(gid=%d, timeout=%d)\n", groupId, timeout); 135 int ret = gContext.device->enroll(gContext.device, hat, groupId, timeout); 136 return reinterpret_cast<jint>(ret); 137} 138 139static jint nativePreEnroll(JNIEnv* env, jobject clazz) { 140 uint64_t ret = gContext.device->pre_enroll(gContext.device); 141 ALOG(LOG_VERBOSE, LOG_TAG, "nativePreEnroll(), result = %" PRId64 "\n", ret); 142 return reinterpret_cast<jlong>((int64_t)ret); 143} 144 145static jint nativeStopEnrollment(JNIEnv* env, jobject clazz) { 146 ALOG(LOG_VERBOSE, LOG_TAG, "nativeStopEnrollment()\n"); 147 int ret = gContext.device->cancel(gContext.device); 148 return reinterpret_cast<jint>(ret); 149} 150 151static jint nativeAuthenticate(JNIEnv* env, jobject clazz, jlong sessionId, jint groupId) { 152 ALOG(LOG_VERBOSE, LOG_TAG, "nativeAuthenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId); 153 int ret = gContext.device->authenticate(gContext.device, sessionId, groupId); 154 return reinterpret_cast<jint>(ret); 155} 156 157static jint nativeStopAuthentication(JNIEnv* env, jobject clazz, jlong sessionId) { 158 ALOG(LOG_VERBOSE, LOG_TAG, "nativeStopAuthentication()\n"); 159 int ret = gContext.device->cancel(gContext.device); 160 return reinterpret_cast<jint>(ret); 161} 162 163static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerId, jint groupId) { 164 ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(fid=%d, gid=%d)\n", fingerId, groupId); 165 fingerprint_finger_id_t finger; 166 finger.fid = fingerId; 167 finger.gid = groupId; 168 int ret = gContext.device->remove(gContext.device, finger); 169 return reinterpret_cast<jint>(ret); 170} 171 172static jint nativeOpenHal(JNIEnv* env, jobject clazz) { 173 ALOG(LOG_VERBOSE, LOG_TAG, "nativeOpenHal()\n"); 174 int err; 175 const hw_module_t *hw_module = NULL; 176 if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) { 177 ALOGE("Can't open fingerprint HW Module, error: %d", err); 178 return 0; 179 } 180 if (NULL == hw_module) { 181 ALOGE("No valid fingerprint module"); 182 return 0; 183 } 184 185 gContext.module = reinterpret_cast<const fingerprint_module_t*>(hw_module); 186 187 if (gContext.module->common.methods->open == NULL) { 188 ALOGE("No valid open method"); 189 return 0; 190 } 191 192 hw_device_t *device = NULL; 193 194 if (0 != (err = gContext.module->common.methods->open(hw_module, NULL, &device))) { 195 ALOGE("Can't open fingerprint methods, error: %d", err); 196 return 0; 197 } 198 199 if (kVersion != device->version) { 200 ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version); 201 // return 0; // FIXME 202 } 203 204 gContext.device = reinterpret_cast<fingerprint_device_t*>(device); 205 err = gContext.device->set_notify(gContext.device, hal_notify_callback); 206 if (err < 0) { 207 ALOGE("Failed in call to set_notify(), err=%d", err); 208 return 0; 209 } 210 211 // Sanity check - remove 212 if (gContext.device->notify != hal_notify_callback) { 213 ALOGE("NOTIFY not set properly: %p != %p", gContext.device->notify, hal_notify_callback); 214 } 215 216 ALOG(LOG_VERBOSE, LOG_TAG, "fingerprint HAL successfully initialized"); 217 return reinterpret_cast<jlong>(gContext.device); 218} 219 220static jint nativeCloseHal(JNIEnv* env, jobject clazz) { 221 return -ENOSYS; // TODO 222} 223 224// ---------------------------------------------------------------------------- 225 226 227// TODO: clean up void methods 228static const JNINativeMethod g_methods[] = { 229 { "nativeAuthenticate", "(JI)I", (void*)nativeAuthenticate }, 230 { "nativeStopAuthentication", "(J)I", (void*)nativeStopAuthentication }, 231 { "nativeEnroll", "(JII)I", (void*)nativeEnroll }, 232 { "nativePreEnroll", "()J", (void*)nativePreEnroll }, 233 { "nativeStopEnrollment", "()I", (void*)nativeStopEnrollment }, 234 { "nativeRemove", "(II)I", (void*)nativeRemove }, 235 { "nativeOpenHal", "()I", (void*)nativeOpenHal }, 236 { "nativeCloseHal", "()I", (void*)nativeCloseHal }, 237 { "nativeInit","(Landroid/os/MessageQueue;" 238 "Lcom/android/server/fingerprint/FingerprintService;)V", (void*)nativeInit } 239}; 240 241int register_android_server_fingerprint_FingerprintService(JNIEnv* env) { 242 jclass clazz = FindClassOrDie(env, FINGERPRINT_SERVICE); 243 gFingerprintServiceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); 244 gFingerprintServiceClassInfo.notify = 245 GetMethodIDOrDie(env, gFingerprintServiceClassInfo.clazz,"notify", "(IIII)V"); 246 int result = RegisterMethodsOrDie(env, FINGERPRINT_SERVICE, g_methods, NELEM(g_methods)); 247 ALOG(LOG_VERBOSE, LOG_TAG, "FingerprintManager JNI ready.\n"); 248 return result; 249} 250 251} // namespace android 252