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