klte: Use new Fingerprint Hal without ValidityService

* Use a fully OSS FPS stack to remove dependency on a service to
  register fingerprints and hacked up touchwiz libs from Samsung

Change-Id: I66ae7fc807a213befdf77d0f09d38f2fbe01df61
This commit is contained in:
ljzyal 2016-09-06 18:49:54 +08:00 committed by Paul Keith
parent 2de5ba9107
commit 2f41fd2d2f
41 changed files with 2191 additions and 1884 deletions

View file

@ -224,14 +224,6 @@ vendor/lib/libwvm.so
vendor/lib/libWVStreamControlAPI_L1.so vendor/lib/libWVStreamControlAPI_L1.so
vendor/lib/mediadrm/libwvdrmengine.so vendor/lib/mediadrm/libwvdrmengine.so
# Fingerprint
bin/vcsFPService
lib/libfpasmtztransport.so
lib/libvalAuth.so
lib/libvcsfp.so
lib/libvfmClient.so
lib/libvfmtztransport.so
# Graphics # Graphics
vendor/lib/egl/eglsubAndroid.so vendor/lib/egl/eglsubAndroid.so
vendor/lib/egl/libEGL_adreno.so vendor/lib/egl/libEGL_adreno.so

View file

@ -1,6 +1,6 @@
# #
# Copyright (C) 2016 The CyanogenMod Project
# Copyright (C) 2016 The Mokee Project # Copyright (C) 2016 The Mokee Project
# Copyright (C) 2016 The CyanogenMod Project
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -21,8 +21,19 @@ include $(CLEAR_VARS)
LOCAL_MODULE := fingerprint.msm8974 LOCAL_MODULE := fingerprint.msm8974
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES := fingerprint.c LOCAL_SRC_FILES := \
LOCAL_SHARED_LIBRARIES := liblog fingerprint.c \
fingerprint_tz.c \
QSEEComAPI.c \
hash.c
LOCAL_C_INCLUDES += \
external/sqlite/dist
LOCAL_SHARED_LIBRARIES := \
liblog \
libsqlite
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

164
fingerprint/QSEEComAPI.c Normal file
View file

@ -0,0 +1,164 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2016 The Mokee Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#define LOG_TAG "Custom_QSEE"
#define LOG_NDEBUG 0
#include <cutils/log.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "QSEEComAPI.h"
struct qcom_keymaster_handle {
void *libhandle;
int (*QSEECom_start_app)(struct QSEECom_handle ** handle, const char* path,
const char* appname, uint32_t size);
int (*QSEECom_shutdown_app)(struct QSEECom_handle **handle);
int (*QSEECom_send_cmd)(struct QSEECom_handle* handle, void *cbuf,
uint32_t clen, void *rbuf, uint32_t rlen);
int (*QSEECom_send_modified_cmd)(struct QSEECom_handle* handle, void *cbuf,
uint32_t clen, void *rbuf, uint32_t rlen,
struct QSEECom_ion_fd_info *ihandle);
int (*QSEECom_set_bandwidth)(struct QSEECom_handle* handle, bool high);
};
typedef struct qcom_keymaster_handle qcom_keymaster_handle_t;
bool init = false;
qcom_keymaster_handle_t* km_handle;
int file_num = 0;
static int qcom_km_get_lib_sym(qcom_keymaster_handle_t* km_handle)
{
km_handle->libhandle = dlopen("libQSEEComAPI.so", RTLD_NOW);
if ( km_handle->libhandle ) {
*(void **)(&km_handle->QSEECom_start_app) =
dlsym(km_handle->libhandle,"QSEECom_start_app");
if (km_handle->QSEECom_start_app == NULL) {
ALOGE("dlsym: Error Loading QSEECom_start_app");
dlclose(km_handle->libhandle );
km_handle->libhandle = NULL;
return -1;
}
*(void **)(&km_handle->QSEECom_shutdown_app) =
dlsym(km_handle->libhandle,"QSEECom_shutdown_app");
if (km_handle->QSEECom_shutdown_app == NULL) {
ALOGE("dlsym: Error Loading QSEECom_shutdown_app");
dlclose(km_handle->libhandle );
km_handle->libhandle = NULL;
return -1;
}
*(void **)(&km_handle->QSEECom_send_cmd) =
dlsym(km_handle->libhandle,"QSEECom_send_cmd");
if (km_handle->QSEECom_send_cmd == NULL) {
ALOGE("dlsym: Error Loading QSEECom_send_cmd");
dlclose(km_handle->libhandle );
km_handle->libhandle = NULL;
return -1;
}
*(void **)(&km_handle->QSEECom_send_modified_cmd) =
dlsym(km_handle->libhandle,"QSEECom_send_modified_cmd");
if (km_handle->QSEECom_send_modified_cmd == NULL) {
ALOGE("dlsym: Error Loading QSEECom_send_modified_cmd");
dlclose(km_handle->libhandle );
km_handle->libhandle = NULL;
return -1;
}
*(void **)(&km_handle->QSEECom_set_bandwidth) =
dlsym(km_handle->libhandle,"QSEECom_set_bandwidth");
if (km_handle->QSEECom_set_bandwidth == NULL) {
ALOGE("dlsym: Error Loading QSEECom_set_bandwidth");
dlclose(km_handle->libhandle );
km_handle->libhandle = NULL;
return -1;
}
} else {
ALOGE("failed to load qseecom library");
return -1;
}
return 0;
}
static int init_qsee()
{
if (init) {
return 0;
}
int ret = 0;
km_handle = (qcom_keymaster_handle_t *)malloc(sizeof(qcom_keymaster_handle_t));
if (km_handle == NULL) {
ALOGE("Memalloc for keymaster handle failed");
return -1;
}
km_handle->libhandle = NULL;
ret = qcom_km_get_lib_sym(km_handle);
if (ret) {
free(km_handle);
return -1;
}
init = true;
return 0;
}
int QSEECom_start_app(struct QSEECom_handle **clnt_handle, const char *path,
const char *fname, uint32_t sb_size)
{
init_qsee();
int ret = 0;
ret = (*km_handle->QSEECom_start_app)(clnt_handle,path,fname,sb_size);
return ret;
}
int QSEECom_shutdown_app(struct QSEECom_handle **handle)
{
init_qsee();
int ret = 0;
ret = (*km_handle->QSEECom_shutdown_app)(handle);
return ret;
}
int QSEECom_send_cmd(struct QSEECom_handle *handle, void *send_buf,
uint32_t sbuf_len, void *rcv_buf, uint32_t rbuf_len)
{
init_qsee();
int ret = 0;
ret = (*km_handle->QSEECom_send_cmd)(handle,send_buf,sbuf_len,rcv_buf,rbuf_len);
return ret;
}
int QSEECom_send_modified_cmd(struct QSEECom_handle *handle, void *send_buf,
uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len,
struct QSEECom_ion_fd_info *ifd_data)
{
init_qsee();
int ret = 0;
ret = (*km_handle->QSEECom_send_modified_cmd)(handle,send_buf,sbuf_len,resp_buf,rbuf_len,ifd_data);
return ret;
}
int QSEECom_set_bandwidth(struct QSEECom_handle *handle, bool high)
{
init_qsee();
int ret = 0;
ret = (*km_handle->QSEECom_set_bandwidth)(handle,high);
return ret;
}

299
fingerprint/QSEEComAPI.h Normal file
View file

@ -0,0 +1,299 @@
/*
* Copyright (c) 2012, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#ifndef __QSEECOMAPI_H_
#define __QSEECOMAPI_H_
/*----------------------------------------------------------------------------
* Include Files
* -------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#define QSEECOM_ALIGN_SIZE 0x40
#define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1)
#define QSEECOM_ALIGN(x) \
((x + QSEECOM_ALIGN_SIZE) & (~QSEECOM_ALIGN_MASK))
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Preprocessor Definitions and Constants
* -------------------------------------------------------------------------*/
/** The memory is locked and non-pageable */
#define MEM_LOCKED 0x00000001
/** The memory is marked non-cacheable */
#define MEM_NON_CACHED 0x00000002
#define QSEECOM_APP_QUERY_FAILED -6
#define QSEECOM_APP_NOT_LOADED -5
#define QSEECOM_APP_ALREADY_LOADED -4
#define QSEECOM_LISTENER_UNREGISTERED -3
#define QSEECOM_LISTENER_ALREADY_REGISTERED -2
#define QSEECOM_LISTENER_REGISTER_FAIL -1
/*----------------------------------------------------------------------------
* Type Declarations
* -------------------------------------------------------------------------*/
struct QSEECom_handle {
unsigned char *ion_sbuffer;
};
struct QSEECom_ion_fd_data {
int32_t fd;
uint32_t cmd_buf_offset;
};
struct QSEECom_ion_fd_info {
struct QSEECom_ion_fd_data data[4];
};
/*----------------------------------------------------------------------------
* Function Declarations and Documentation
* -------------------------------------------------------------------------*/
/**
* @brief Open a handle to the QSEECom device.
*
* - Load a secure application. The application will be verified that it is
* secure by digital signature verification.
* Allocate memory for sending requests to the QSAPP
*
* Note/Comments:
* There is a one-to-one relation for a HLOS client and a QSAPP;
* meaning that only one app can communicate to a QSAPP at a time.
*
* Please note that there is difference between an application and a listener
* service. A QSAPP must be loaded at the request of the HLOS,
* and all requests are orginated by the HLOS client.
* A listener service on the otherhand is started during start-up by a
* daemon, qseecomd.
*
* A HLOS application may create mutiple handles to the QSAPP
*
* @param[in/out] handle The device handle
* @param[in] fname The directory and filename to load.
* @param[in] sb_size Size of the shared buffer memory for sending requests.
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_start_app(struct QSEECom_handle **clnt_handle, const char *path,
const char *fname, uint32_t sb_size);
/**
* @brief Close the application associated with the handle.
*
* - Unload a secure application. The driver will verify if there exists
* any other applications that are communicating with the QSAPP to which
* the "handle" is tied.
* - De-allocate memory for sending requests to QSAPP.
*
* @param[in] handle The device handle
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_shutdown_app(struct QSEECom_handle **handle);
/**
* @brief Open a handle to the QSEECom device.
*
* - Load an external elf. The elf will be verified that it is
* secure by digital signature verification.
*
* A HLOS application may create mutiple opens (only one is permitted for the
* app, but each listener service can open a unique device in the same HLOS app
* /executable.
* @param[in/out] handle The device handle
* @param[in] fname The directory and filename to load.
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_load_external_elf(struct QSEECom_handle **clnt_handle, const char *path,
const char *fname);
/**
* @brief Close the external elf
*
* - Unload an external elf.
*
* @param[in] handle The device handle
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_unload_external_elf(struct QSEECom_handle **handle);
/**
* @brief Register an HLOS listener service. This allows messages from QSAPP
* to be received.
*
* @param[in] handle The device handle
* @param[in] lstnr_id The listener service identifier. This ID must be uniquely
* assigned to avoid any collisions.
* @param[in] sb_length Shared memory buffer between OS and QSE.
* @param[in] flags Provide the shared memory flags attributes.
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*
*/
int QSEECom_register_listener(struct QSEECom_handle **handle,
uint32_t lstnr_id, uint32_t sb_length, uint32_t flags);
/**
* @brief Unregister a listener service.
*
* @param[in] handle The device handle
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_unregister_listener(struct QSEECom_handle *handle);
/**
* @brief Send QSAPP a "user" defined buffer (may contain some message/
* command request) and receives a response from QSAPP in receive buffer.
* The HLOS client writes to the send_buf, where QSAPP writes to the rcv_buf.
* This is a blocking call.
*
* @param[in] handle The device handle
* @param[in] send_buf The buffer to be sent.
* If using ion_sbuffer, ensure this
* QSEECOM_BUFFER_ALIGN'ed.
* @param[in] sbuf_len The send buffer length
* If using ion_sbuffer, ensure length is
* multiple of QSEECOM_BUFFER_ALIGN.
* @param[in] rcv_buf The QSEOS returned buffer.
* If using ion_sbuffer, ensure this is
* QSEECOM_BUFFER_ALIGN'ed.
* @param[in] rbuf_len The returned buffer length.
* If using ion_sbuffer, ensure length is
* multiple of QSEECOM_BUFFER_ALIGN.
* @param[in] rbuf_len The returned buffer length.
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_send_cmd(struct QSEECom_handle *handle, void *send_buf,
uint32_t sbuf_len, void *rcv_buf, uint32_t rbuf_len);
/**
* @brief Send QSAPP a "user" defined buffer (may contain some message/
* command request) and receives a response from QSAPP in receive buffer.
* This API is same as send_cmd except it takes in addition parameter,
* "ifd_data". This "ifd_data" holds information (ion fd handle and
* cmd_buf_offset) used for modifying data in the message in send_buf
* at an offset. Essentailly, it has the ion fd handle information to
* retrieve physical address and modify the message in send_buf at the
* mentioned offset.
*
* The HLOS client writes to the send_buf, where QSAPP writes to the rcv_buf.
* This is a blocking call.
*
* @param[in] handle The device handle
* @param[in] send_buf The buffer to be sent.
* If using ion_sbuffer, ensure this
* QSEECOM_BUFFER_ALIGN'ed.
* @param[in] sbuf_len The send buffer length
* If using ion_sbuffer, ensure length is
* multiple of QSEECOM_BUFFER_ALIGN.
* @param[in] rcv_buf The QSEOS returned buffer.
* If using ion_sbuffer, ensure this is
* QSEECOM_BUFFER_ALIGN'ed.
* @param[in] rbuf_len The returned buffer length.
* If using ion_sbuffer, ensure length is
* multiple of QSEECOM_BUFFER_ALIGN.
* @param[in] QSEECom_ion_fd_info data related to memory allocated by ion.
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_send_modified_cmd(struct QSEECom_handle *handle, void *send_buf,
uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len,
struct QSEECom_ion_fd_info *ifd_data);
/**
* @brief Receive a service defined buffer.
*
* @param[in] handle The device handle
* @param[out] buf The buffer that is received
* @param[in] len The receive buffer length
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_receive_req(struct QSEECom_handle *handle,
void *buf, uint32_t len);
/**
* @brief Send a response based on the previous QSEECom_receive_req.
*
* This allows a listener service to receive a command (e.g. read file abc).
* The service can then handle the request from QSEECom_receive_req, and provide
* that information back to QSAPP.
*
* This allows the HLOS to act as the server and QSAPP to behave as the client.
*
* @param[in] handle The device handle
* @param[out] send_buf The buffer to be returned back to QSAPP
* @param[in] len The send buffer length
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_send_resp(struct QSEECom_handle *handle,
void *send_buf, uint32_t len);
/**
* @brief Set the bandwidth for QSEE.
*
* This API resulst in improving the performance on the Crypto hardware
* in QSEE. It should be called before issuing send_cmd/send_modified_cmd
* for commands that requires using the crypto hardware on the QSEE.
* Typically this API should be called before issuing the send request to
* enable high performance mode and after completion of the send_cmd to
* resume to low performance and hence to low power mode.
*
* This allows the clients of QSEECom to set the QSEE cyptpo HW bus
* bandwidth to high/low.
*
* @param[in] high Set to 1 to enable bandwidth.
*
* @return Zero on success, negative on failure. errno will be set on
* error.
*/
int QSEECom_set_bandwidth(struct QSEECom_handle *handle, bool high);
/**
* @brief Query QSEE to check if app is loaded.
*
* This API queries QSEE to see if the app is loaded or not.
*
* @param[in] app_name Name of the app.
*
* @return QSEECOM_APP_QUERY_FAILED/QSEECOM_APP_NOT_LOADED/QSEECOM_APP_LOADED.
*/
int QSEECom_app_load_query(struct QSEECom_handle *handle, char *app_name);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2014 The Android Open Source Project * Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project * Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project * Copyright (C) 2016 The CyanogenMod Project
* *
@ -21,71 +21,288 @@
#include <errno.h> #include <errno.h>
#include <endian.h> #include <endian.h>
#include <fcntl.h>
#include <inttypes.h> #include <inttypes.h>
#include <malloc.h> #include <malloc.h>
#include <signal.h>
#include <sqlite3.h>
#include <string.h> #include <string.h>
#include <cutils/log.h>
#include <cutils/sockets.h>
#include <hardware/hardware.h>
#include <hardware/fingerprint.h>
#include <unistd.h> #include <unistd.h>
#include <cutils/log.h>
#include <sys/ioctl.h>
#include <hardware/hardware.h>
#include <hardware/fingerprint.h>
#include "fp_klte.h" #include "fp_klte.h"
#include "fingerprint_tz.h"
#include "hash.h"
#define MAX_COMM_CHARS 128 typedef struct vcs_fingerprint_device_t {
#define MAX_NUM_FINGERS 5 fingerprint_device_t device; // "inheritance"
#define SOCKET_NAME_SEND "validityservice" uint64_t op_id;
#define SOCKET_NAME_RECEIVE "validityservice_callback" uint64_t challenge;
uint64_t user_id;
uint64_t group_id;
uint64_t secure_user_id;
uint64_t authenticator_id;
uint32_t active_gid;
sqlite3 *db;
pthread_mutex_t lock;
} vcs_fingerprint_device_t;
/******************************************************************************/ extern trust_zone_t tz;
static void checkinit(vcs_fingerprint_device_t* vdev) { //wait for hal connect validity service vcs_sensor_t sensor;
while(!vdev->init)
sleep(1);
}
static int sendcommand(vcs_fingerprint_device_t* vdev, uint8_t* command, int num) { /***************************************Sensor***************************************/
int ret = -1; int sensor_uninit() {
char answer[255];
if (fd_write(vdev->send_fd, command, num) != num) {
ALOGE("cannot send command to service");
//close(vdev->send_fd);
return ret;
}
if (fd_read(vdev->send_fd, answer, 255))
ret = atoi(answer);
return ret;
}
static int getfingermask(vcs_fingerprint_device_t* vdev) {
uint8_t command_getlist[2] = {CALL_GET_ENROLLED_FINGER_LIST, (uint8_t)vdev->active_gid};
return sendcommand(vdev, command_getlist, 2);
}
static int initService(vcs_fingerprint_device_t* vdev) {
ALOGV("----------------> %s ----------------->", __FUNCTION__); ALOGV("----------------> %s ----------------->", __FUNCTION__);
int ret = -EINVAL; int ret = 0;
while (vdev->send_fd <= 0) { if (!sensor.init)
vdev->send_fd = socket_local_client(SOCKET_NAME_SEND, ANDROID_SOCKET_NAMESPACE_ABSTRACT,SOCK_STREAM); return ret;
if (vdev->send_fd < 0) { ioctl(sensor.fd, VFSSPI_IOCTL_RESET_SPI_CONFIGURATION);
ALOGW("cannot open validity service!"); ioctl(sensor.fd, VFSSPI_IOCTL_DISABLE_SPI_CLOCK);
sleep(1); ioctl(sensor.fd, VFSSPI_IOCTL_DEVICE_SUSPEND);
} ioctl(sensor.fd, VFSSPI_IOCTL_POWER_OFF);
} sensor.init = false;
uint8_t command[1] = {CALL_INITSERVICE};
ret = sendcommand(vdev, command, 1);
vdev->authenticator_id = getfingermask(vdev);
vdev->init = true;
return ret; return ret;
} }
static void send_error_notice(vcs_fingerprint_device_t* vdev, fingerprint_error_t error_info) { int sensor_init() {
ALOGV("----------------> %s ----------------->", __FUNCTION__); ALOGV("----------------> %s ----------------->", __FUNCTION__);
int ret = 0;
int clock = 0;
if (sensor.init)
return ret;
ioctl(sensor.fd, VFSSPI_IOCTL_POWER_ON);
clock = 65535;
ioctl(sensor.fd, VFSSPI_IOCTL_SET_CLK, &clock);
ioctl(sensor.fd, VFSSPI_IOCTL_DEVICE_RESET);
ioctl(sensor.fd, VFSSPI_IOCTL_SET_SPI_CONFIGURATION);
clock = 4800;
ioctl(sensor.fd, VFSSPI_IOCTL_SET_CLK, &clock);
sensor.init = true;
return ret;
}
void sensor_process_signal(int signum) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
ALOGV("%s: signal %d received", __FUNCTION__, signum);
int flag = 0;
if (tz.timeout.timeout_thread) {
pthread_mutex_lock(&tz.timeout.lock);
pthread_cond_signal(&tz.timeout.cond);
pthread_mutex_unlock(&tz.timeout.lock);
//pthread_join(tz.timeout.timeout_thread, NULL);
tz.timeout.timeout_thread = 0;
}
pthread_mutex_lock(&sensor.lock);
if (get_tz_state() != STATE_IDLE && get_tz_state() != STATE_CANCEL)
sensor.signal = true;
ioctl(sensor.fd, VFSSPI_IOCTL_SET_DRDY_INT, &flag);
pthread_cond_signal(&sensor.cond);
pthread_mutex_unlock(&sensor.lock);
}
int sensor_register() {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
struct vfsspi_iocRegSignal usrSignal;
int ret = 0;
struct sigaction sa_usr;
sa_usr.sa_flags = 0;
sa_usr.sa_handler = sensor_process_signal;
sigaction(SIGUSR2, &sa_usr, NULL);
usrSignal.userPID = getpid();
usrSignal.signalID = SIGUSR2;
ioctl(sensor.fd, VFSSPI_IOCTL_REGISTER_DRDY_SIGNAL, &usrSignal);
return ret;
}
int sensor_capture_start() {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
int ret = 0;
int flag = 1;
ret = ioctl(sensor.fd, VFSSPI_IOCTL_SET_DRDY_INT, &flag);
return ret;
}
/***************************************Database***************************************/
int db_check_and_create_table(void* device) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
char* errmsg;
int ret = 0;
char cmd[MAX_DATABASE_CMD];
sprintf(cmd, "create table gid_%d(id integer, data blob, payload blob)", vdev->active_gid);
ret = sqlite3_exec(vdev->db, cmd, NULL, NULL, &errmsg);
return ret;
}
int db_convert_old_db(vcs_fingerprint_device_t* vdev) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
int ret = 0;
sqlite3 *db;
sqlite3_stmt *stat;
char cmd[MAX_DATABASE_CMD];
int idx = 0;
memset(tz.finger, 0, MAX_NUM_FINGERS * sizeof(finger_t));
ret = sqlite3_open(SAMSUNG_FP_DB_PATH, &db);
if (ret != SQLITE_OK) {
ALOGE("Open samsung finger database failed!");
return -1;
}
sprintf(cmd, "select * from enrollments");
sqlite3_prepare(db, cmd, -1, &stat, 0);
while(1) {
int ret = sqlite3_step(stat);
if (ret != SQLITE_ROW) {
break;
}
int id = sqlite3_column_int(stat, 1);
const void *data = sqlite3_column_blob(stat, 2);
int len = sqlite3_column_bytes(stat, 2);
memcpy(tz.finger[id].data, data, len);
ALOGV("read fingerprint data from samsung fp database: id=%d", id);
tz.finger[id].exist = true;
}
sqlite3_finalize(stat);
memset(cmd, 0, MAX_DATABASE_CMD);
sprintf(cmd, "select * from properties");
sqlite3_prepare(db, cmd, -1, &stat, 0);
sqlite3_step(stat);
const void *payload = sqlite3_column_blob(stat, 2);
int len = sqlite3_column_bytes(stat, 2);
for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) {
if (tz.finger[idx].exist) {
memcpy(tz.finger[idx].payload, payload, len);
db_write_to_db(vdev, false, idx);
}
}
sqlite3_finalize(stat);
ret = sqlite3_close(db);
if (ret != SQLITE_OK) {
ALOGE("Close samsung finger database failed!");
return -1;
}
ret = remove(SAMSUNG_FP_DB_PATH);
if (ret) {
ALOGE("Cannot remove Samsung fingerprint database");
}
return ret;
}
int db_read_to_tz(void* device) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
char* errmsg;
int ret = 0;
char cmd[MAX_DATABASE_CMD];
sqlite3_stmt *stat;
db_check_and_create_table(vdev);
if (!access(SAMSUNG_FP_DB_PATH, 0)) {
ALOGI("Samsung fingerprint database exist! Convert it");
return db_convert_old_db(vdev);
}
memset(tz.finger, 0, MAX_NUM_FINGERS * sizeof(finger_t));
sprintf(cmd, "select * from gid_%d", vdev->active_gid);
sqlite3_prepare(vdev->db, cmd, -1, &stat, 0);
while(1) {
int ret = sqlite3_step(stat);
if (ret != SQLITE_ROW) {
break;
}
int id = sqlite3_column_int(stat, 0);
const void *data = sqlite3_column_blob(stat, 1);
memcpy(tz.finger[id].data, data, FINGER_DATA_MAX_LENGTH);
const void *payload = sqlite3_column_blob(stat, 2);
memcpy(tz.finger[id].payload, payload, PAYLOAD_MAX_LENGTH);
ALOGV("read fingerprint data from database: id=%d", id);
tz.finger[id].exist = true;
}
sqlite3_finalize(stat);
return 0;
}
int db_write_to_db(void* device, bool remove, int fid) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
char* errmsg;
int ret = 0;
char cmd[MAX_DATABASE_CMD];
sqlite3_stmt *stat;
if (remove) {
sprintf(cmd, "delete from gid_%d where id=%d", vdev->active_gid, fid);
ret = sqlite3_exec(vdev->db, cmd, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
ALOGE("Remove finger from database failed!");
}
memset(&tz.finger[fid], 0, sizeof(finger_t));
} else {
sprintf(cmd, "insert into gid_%d(id, data, payload) values( %d, ?, ?)", vdev->active_gid, fid);
sqlite3_prepare(vdev->db, cmd, -1, &stat, 0);
sqlite3_bind_blob(stat, 1, tz.finger[fid].data, (int)FINGER_DATA_MAX_LENGTH, NULL);
sqlite3_bind_blob(stat, 2, tz.finger[fid].payload, (int)PAYLOAD_MAX_LENGTH, NULL);
ret = sqlite3_step(stat);
sqlite3_finalize(stat);
}
return ret;
}
int db_init(void* device) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
int ret = 0;
ret = sqlite3_open(FINGER_DATABASE_FILENAME, &vdev->db);
if (ret != SQLITE_OK) {
ALOGE("Open finger database failed!");
return -1;
}
return db_read_to_tz(vdev);
}
int db_uninit(void* device) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
int ret = 0;
ret = sqlite3_close(vdev->db);
if (ret != SQLITE_OK) {
ALOGE("Close finger database failed!");
}
return ret;
}
/***************************************notice***************************************/
fingerprint_acquired_info_t convert_ret_to_acquired_info(int acquired_ret) { //TODO
ALOGV("----------------> %s ----------------->acquired_ret=%d", __FUNCTION__, acquired_ret);
fingerprint_acquired_info_t ret = FINGERPRINT_ACQUIRED_GOOD;
switch (acquired_ret) {
case 0:
break;
default:
ret = FINGERPRINT_ACQUIRED_INSUFFICIENT;
}
return ret;
}
void send_error_notice(void* device, int error_info_int) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
fingerprint_error_t error_info = (fingerprint_error_t)error_info_int;
fingerprint_msg_t msg = {0}; fingerprint_msg_t msg = {0};
msg.type = FINGERPRINT_ERROR; msg.type = FINGERPRINT_ERROR;
msg.data.error = error_info; msg.data.error = error_info;
ALOGI("error_info=%d", (int)error_info); ALOGV("recevied error notice! error_info=%d", (int)error_info);
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->device.notify(&msg); vdev->device.notify(&msg);
@ -94,8 +311,10 @@ static void send_error_notice(vcs_fingerprint_device_t* vdev, fingerprint_error_
return; return;
} }
static void send_acquired_notice(vcs_fingerprint_device_t* vdev, fingerprint_acquired_info_t acquired_info) { void send_acquired_notice(void* device, int acquired_ret) {
ALOGV("----------------> %s ----------------->", __FUNCTION__); ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
fingerprint_acquired_info_t acquired_info = convert_ret_to_acquired_info(acquired_ret);
fingerprint_msg_t acqu_msg = {0}; fingerprint_msg_t acqu_msg = {0};
acqu_msg.type = FINGERPRINT_ACQUIRED; acqu_msg.type = FINGERPRINT_ACQUIRED;
@ -109,22 +328,21 @@ static void send_acquired_notice(vcs_fingerprint_device_t* vdev, fingerprint_acq
return; return;
} }
static void send_enroll_notice(vcs_fingerprint_device_t* vdev, int fid, int remaining) { void send_enroll_notice(void* device, int fid, int remaining) {
ALOGV("----------------> %s -----------------> fid %d", __FUNCTION__, fid); ALOGV("----------------> %s -----------------> fid %d", __FUNCTION__, fid);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
if (fid == 0) { if (fid == 0) {
ALOGD("Fingerprint ID is zero (invalid)"); ALOGE("Fingerprint ID is zero (invalid)");
return; return;
} }
if (vdev->secure_user_id == 0) { if (vdev->secure_user_id == 0) {
ALOGD("Secure user ID is zero (invalid)"); ALOGE("Secure user ID is zero (invalid)");
return; return;
} }
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->listener.state = STATE_SCAN;
fingerprint_msg_t msg = {0}; fingerprint_msg_t msg = {0};
msg.type = FINGERPRINT_TEMPLATE_ENROLLING; msg.type = FINGERPRINT_TEMPLATE_ENROLLING;
msg.data.enroll.finger.fid = fid; msg.data.enroll.finger.fid = fid;
@ -136,8 +354,9 @@ static void send_enroll_notice(vcs_fingerprint_device_t* vdev, int fid, int rema
return; return;
} }
static void send_authenticated_notice(vcs_fingerprint_device_t* vdev, int fid) { void send_authenticated_notice(void* device, int fid) {
ALOGV("----------------> %s ----------------->", __FUNCTION__); ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
send_acquired_notice(vdev, FINGERPRINT_ACQUIRED_GOOD); send_acquired_notice(vdev, FINGERPRINT_ACQUIRED_GOOD);
@ -163,8 +382,9 @@ static void send_authenticated_notice(vcs_fingerprint_device_t* vdev, int fid) {
return; return;
} }
static void send_remove_notice(vcs_fingerprint_device_t* vdev, int fid) { void send_remove_notice(void* device, int fid) {
ALOGV("----------------> %s ----------------->fid=%d", __FUNCTION__, fid); ALOGV("----------------> %s ----------------->fid=%d", __FUNCTION__, fid);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
fingerprint_msg_t msg = {0}; fingerprint_msg_t msg = {0};
msg.type = FINGERPRINT_TEMPLATE_REMOVED; msg.type = FINGERPRINT_TEMPLATE_REMOVED;
@ -177,20 +397,14 @@ static void send_remove_notice(vcs_fingerprint_device_t* vdev, int fid) {
return; return;
} }
/******************************************************************************/ /***************************************HAL function***************************************/
static uint64_t get_64bit_rand() {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
uint64_t r = (((uint64_t)rand()) << 32) | ((uint64_t)rand());
return r != 0 ? r : 1;
}
static uint64_t fingerprint_get_auth_id(struct fingerprint_device* device) { static uint64_t fingerprint_get_auth_id(struct fingerprint_device* device) {
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
ALOGV("----------------> %s ----------------->", __FUNCTION__); ALOGV("----------------> %s ----------------->", __FUNCTION__);
uint64_t authenticator_id = 0; uint64_t authenticator_id = 0;
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->authenticator_id = getfingermask(vdev); vdev->authenticator_id = hash_file(FINGER_DATABASE_FILENAME);
authenticator_id = vdev->authenticator_id; authenticator_id = vdev->authenticator_id;
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
@ -199,9 +413,11 @@ static uint64_t fingerprint_get_auth_id(struct fingerprint_device* device) {
static int fingerprint_set_active_group(struct fingerprint_device *device, uint32_t gid, static int fingerprint_set_active_group(struct fingerprint_device *device, uint32_t gid,
const char __unused *path) { const char __unused *path) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->active_gid = gid; vdev->active_gid = gid;
db_read_to_tz(vdev);
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
return 0; return 0;
@ -215,33 +431,24 @@ static int fingerprint_authenticate(struct fingerprint_device *device,
int ret = 0; int ret = 0;
ALOGI("auth: op_id=%llu ",operation_id); ALOGI("auth: op_id=%llu ",operation_id);
checkinit(vdev);
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->op_id = operation_id; vdev->op_id = operation_id;
vdev->listener.state = STATE_SCAN; ret = vcs_start_authenticate(vdev);
uint8_t command[2] = {CALL_IDENTIFY, (uint8_t)vdev->active_gid};
ret = sendcommand(vdev, command, 2);
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
// Always return successful return ret;
return 0;
} }
static int fingerprint_enroll(struct fingerprint_device *device, static int fingerprint_enroll(struct fingerprint_device *device,
const hw_auth_token_t *hat, const hw_auth_token_t *hat,
uint32_t __unused gid, uint32_t __unused gid,
uint32_t __unused timeout_sec) { uint32_t timeout_sec) {
ALOGD("fingerprint_enroll"); ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
int ret = -EINVAL; int ret = -EINVAL;
int fingermask = 0;
int idx = 1; int idx = 1;
uint8_t command[3] = {CALL_ENROLL, (uint8_t)vdev->active_gid, 0};
checkinit(vdev);
if (!hat) { if (!hat) {
ALOGW("%s: null auth token", __func__); ALOGW("%s: null auth token", __func__);
@ -263,26 +470,21 @@ static int fingerprint_enroll(struct fingerprint_device *device,
vdev->user_id = hat->user_id; vdev->user_id = hat->user_id;
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->listener.state = STATE_ENROLL;
fingermask = getfingermask(vdev); for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) {
ALOGI("fingerprint_enroll: fingermask=%d", fingermask); if (!tz.finger[idx].exist) {
for (idx = 1; idx <= MAX_NUM_FINGERS; idx++)
if (!((fingermask >> idx) & 1))
break; break;
}
command[2] = (uint8_t)idx; }
ret = sendcommand(vdev, command, 3); if (idx > MAX_NUM_FINGERS) {
send_error_notice(vdev, FINGERPRINT_ERROR_NO_SPACE);
pthread_mutex_unlock(&vdev->lock);
return -1;
}
ret = vcs_start_enroll(vdev, timeout_sec);
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
ALOGI("enroll ret=%d",ret); ALOGV("enroll ret=%d",ret);
// workaround
if (ret == 1) {
ret = 0;
}
vdev->authenticator_id = getfingermask(vdev);
return ret; return ret;
} }
@ -292,7 +494,7 @@ static uint64_t fingerprint_pre_enroll(struct fingerprint_device *device) {
uint64_t challenge = 0; uint64_t challenge = 0;
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
challenge = get_64bit_rand(); challenge = hash_string(tz.auth_token);
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->challenge = challenge; vdev->challenge = challenge;
@ -316,15 +518,27 @@ static int fingerprint_cancel(struct fingerprint_device *device) {
ALOGV("----------------> %s ----------------->", __FUNCTION__); ALOGV("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
int ret = 0; int ret = 0;
int flag = 0;
checkinit(vdev); if (tz.timeout.timeout_thread) {
pthread_mutex_lock(&tz.timeout.lock);
pthread_mutex_lock(&vdev->lock); pthread_cond_signal(&tz.timeout.cond);
vdev->listener.state = STATE_IDLE; pthread_mutex_unlock(&tz.timeout.lock);
pthread_join(tz.timeout.timeout_thread, NULL);
uint8_t command[1] = {CALL_CANCEL}; tz.timeout.timeout_thread = 0;
ret = sendcommand(vdev, command, 1); }
pthread_mutex_unlock(&vdev->lock); if (get_tz_state() != STATE_IDLE && get_tz_state() != STATE_CANCEL) {
set_tz_state(STATE_CANCEL);
ioctl(sensor.fd, VFSSPI_IOCTL_SET_DRDY_INT, &flag);
pthread_mutex_lock(&sensor.lock);
pthread_cond_signal(&sensor.cond);
pthread_mutex_unlock(&sensor.lock);
while (1) {
usleep(100000);
if (tz.state == STATE_IDLE)
break;
}
}
return ret; return ret;
} }
@ -337,17 +551,12 @@ static int fingerprint_enumerate(struct fingerprint_device *device,
return -1; return -1;
} }
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
int num = 0; int num = 0;
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
num = vcs_get_enrolled_finger_num();
int fingermask = getfingermask(vdev);
ALOGI("fingerprint_enumerate: fingermask=%d", fingermask);
int idx = 0;
for (idx = 0; idx < MAX_NUM_FINGERS; idx++)
if ((fingermask >> (idx + 1)) & 1)
num++;
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
return num; return num;
@ -355,7 +564,7 @@ static int fingerprint_enumerate(struct fingerprint_device *device,
static int fingerprint_remove(struct fingerprint_device *device, static int fingerprint_remove(struct fingerprint_device *device,
uint32_t __unused gid, uint32_t fid) { uint32_t __unused gid, uint32_t fid) {
int idx = 0, ret = 0; int ret = 0;
ALOGV("----------------> %s -----------------> fid %d", __FUNCTION__, fid); ALOGV("----------------> %s -----------------> fid %d", __FUNCTION__, fid);
if (device == NULL) { if (device == NULL) {
ALOGE("Can't remove fingerprint (gid=%d, fid=%d); " ALOGE("Can't remove fingerprint (gid=%d, fid=%d); "
@ -366,50 +575,31 @@ static int fingerprint_remove(struct fingerprint_device *device,
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
uint8_t command[3] = {CALL_REMOVE, (uint8_t)vdev->active_gid, 0};
checkinit(vdev);
if (fid == 0) { if (fid == 0) {
// Delete all fingerprints // Delete all fingerprints
command[2] = 21; int idx = 1;
int fingermask = getfingermask(vdev); for (idx = 1; idx <= MAX_NUM_FINGERS; idx++)
if (tz.finger[idx].exist) {
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
ret = sendcommand(vdev, command, 3); ret = db_write_to_db(vdev, true, idx);
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
if (ret == 0) { if (ret == 0) {
pthread_mutex_lock(&vdev->lock); send_remove_notice(vdev, idx);
pthread_mutex_unlock(&vdev->lock); }
int idx = 0;
for (idx = 0; idx < MAX_NUM_FINGERS; idx++)
if ((fingermask >> (idx + 1)) & 1) {
send_remove_notice(vdev, idx + 1);
} }
} // end if
vdev->listener.state = STATE_IDLE;
} else { } else {
// Delete one fingerprint // Delete one fingerprint
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
ret = db_write_to_db(vdev, true, fid);
command[2] = (uint8_t)fid;
ret = sendcommand(vdev, command, 3);
vdev->listener.state = STATE_IDLE;
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
if (ret == 0) {
// Always send remove notice
send_remove_notice(vdev, fid); send_remove_notice(vdev, fid);
} }
pthread_mutex_lock(&vdev->lock);
int fingermask = getfingermask(vdev);
if (fingermask == 0) { // All finger are removed
command[2] = 21;
sendcommand(vdev, command, 3);
} }
pthread_mutex_unlock(&vdev->lock);
if (ret) { if (ret) {
ALOGE("Can't remove finger %d", fid);
send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_REMOVE); send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_REMOVE);
} }
@ -427,7 +617,6 @@ static int set_notify_callback(struct fingerprint_device *device,
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
vdev->listener.state = STATE_IDLE;
device->notify = notify; device->notify = notify;
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
ALOGD("fingerprint callback notification set"); ALOGD("fingerprint callback notification set");
@ -435,78 +624,6 @@ static int set_notify_callback(struct fingerprint_device *device,
return 0; return 0;
} }
static worker_state_t getListenerState(vcs_fingerprint_device_t* dev) {
ALOGV("----------------> %s ----------------->", __FUNCTION__);
worker_state_t state = STATE_IDLE;
pthread_mutex_lock(&dev->lock);
state = dev->listener.state;
pthread_mutex_unlock(&dev->lock);
return state;
}
static void* listenerSocket(void* data) {
ALOGI("----------------> %s ----------------->", __FUNCTION__);
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)data;
while (vdev->receive_fd <= 0) {
vdev->receive_fd = socket_local_client(SOCKET_NAME_RECEIVE, ANDROID_SOCKET_NAMESPACE_ABSTRACT,SOCK_STREAM);
if (vdev->receive_fd < 0) {
ALOGW("listener cannot open fingerprint listener service");
sleep(1);
}
}
initService(vdev);
pthread_mutex_lock(&vdev->lock);
vdev->listener.state = STATE_IDLE;
pthread_mutex_unlock(&vdev->lock);
while (1) {
int size = 0;
char buffer[MAX_COMM_CHARS] = {0};
if (getListenerState(vdev) == STATE_EXIT) {
ALOGD("Received request to exit listener thread");
goto done;
}
if ((size = fd_read(vdev->receive_fd, buffer,
sizeof(buffer) - 1)) > 0) {
buffer[size] = '\0';
int type, info, info_ex;
sscanf(buffer, "%d:%d:%d", &type, &info, &info_ex);
switch (type) {
case 1: //error
send_error_notice(vdev, info);
break;
case 2: //enroll
send_enroll_notice(vdev, info, info_ex);
break;
case 3: //removed
send_remove_notice(vdev, info);
break;
case 4: //acquired
send_acquired_notice(vdev, info);
break;
case 5: //authenticated
send_authenticated_notice(vdev, info);
break;
default:
ALOGE("unknow type:%d", type);
}
} else {
ALOGE("fingerprint listener receive failure");
break;
}
}
done:
ALOGD("Listener exit !!");
done_quiet:
close(vdev->receive_fd);
return NULL;
}
static int fingerprint_close(hw_device_t* device) { static int fingerprint_close(hw_device_t* device) {
ALOGV("----------------> %s ----------------->", __FUNCTION__); ALOGV("----------------> %s ----------------->", __FUNCTION__);
if (device == NULL) { if (device == NULL) {
@ -516,18 +633,18 @@ static int fingerprint_close(hw_device_t* device) {
vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device; vcs_fingerprint_device_t* vdev = (vcs_fingerprint_device_t*)device;
checkinit(vdev);
pthread_mutex_lock(&vdev->lock); pthread_mutex_lock(&vdev->lock);
// Ask listener thread to exit db_uninit(vdev);
vdev->listener.state = STATE_EXIT; vcs_init();
uint8_t command[1] = {CALL_CLEANUP}; vcs_stop_auth_session();
sendcommand(vdev, command, 1); vcs_uninit();
sensor_uninit();
pthread_mutex_unlock(&vdev->lock); pthread_mutex_unlock(&vdev->lock);
pthread_join(vdev->listener.thread, NULL);
pthread_mutex_destroy(&vdev->lock); pthread_mutex_destroy(&vdev->lock);
close(vdev->send_fd); pthread_mutex_destroy(&sensor.lock);
pthread_mutex_destroy(&tz.lock);
pthread_mutex_destroy(&tz.timeout.lock);
free(vdev); free(vdev);
return 0; return 0;
@ -568,15 +685,39 @@ static int fingerprint_open(const hw_module_t* module, const char __unused *id,
vdev->device.notify = NULL; vdev->device.notify = NULL;
vdev->active_gid = 0; vdev->active_gid = 0;
vdev->init = false; memset(&tz, 0, sizeof(trust_zone_t));
pthread_mutex_init(&vdev->lock, NULL); pthread_mutex_init(&vdev->lock, NULL);
if (pthread_create(&vdev->listener.thread, NULL, listenerSocket, vdev) != pthread_mutex_init(&sensor.lock, NULL);
0) pthread_mutex_init(&tz.lock, NULL);
return -1; pthread_mutex_init(&tz.timeout.lock, NULL);
pthread_cond_init(&tz.timeout.cond, NULL);
pthread_cond_init(&sensor.cond, NULL);
tz.timeout.timeout_thread = 0;
*device = &vdev->device.common; *device = &vdev->device.common;
memset(&sensor, 0, sizeof(vcs_sensor_t));
sensor.fd = open(SENSOR_FILE_NAME, O_RDWR);
if (sensor.fd < 0) {
ALOGE("Open sensor error!");
return -1;
}
sensor_init();
sensor_register();
sensor_uninit();
pthread_mutex_lock(&vdev->lock);
sensor_init();
db_init(vdev);
vcs_init();
vcs_uninit();
vcs_init();
vcs_start_auth_session();
vcs_uninit();
sensor_uninit();
pthread_mutex_unlock(&vdev->lock);
return 0; return 0;
} }

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2016 The Mokee Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#ifndef __FINGERPRINT_COMMON_H_
#define __FINGERPRINT_COMMON_H_
#include <stdbool.h>
#define SB_LENGTH (0x100000)
#define BUFFER_LENGTH (0x19000)
#define AUTH_TOKEN_LENGTH (0x70)
#define AUTH_SESSION_TOKEN_LENGTH (0x20)
#define CALIBRATE_DATA_MAX_LENGTH (0x500c)
#define FINGER_DATA_MAX_LENGTH (0x2900)
#define PAYLOAD_MAX_LENGTH (0x24)
#define MAX_NUM_FINGERS (5)
typedef enum worker_state_t {
STATE_IDLE = 0,
STATE_ENROLL,
STATE_SCAN,
STATE_CANCEL
} worker_state_t;
typedef struct vcs_sensor_t {
int fd;
bool init;
bool signal;
pthread_cond_t cond;
pthread_mutex_t lock;
}vcs_sensor_t;
typedef struct finger_t {
bool exist;
char data[FINGER_DATA_MAX_LENGTH];
char payload[PAYLOAD_MAX_LENGTH];
}finger_t;
typedef struct timeout_t {
uint32_t timeout;
pthread_t timeout_thread;
pthread_cond_t cond;
pthread_mutex_t lock;
}timeout_t;
typedef struct trust_zone_t {
bool init;
worker_state_t state;
struct QSEECom_handle *qhandle;
bool auth_session_opend;
char auth_token[AUTH_TOKEN_LENGTH];
char auth_session_token[AUTH_SESSION_TOKEN_LENGTH];
int calibrate_len;
char calibrate_data[CALIBRATE_DATA_MAX_LENGTH];
finger_t finger[MAX_NUM_FINGERS + 1]; // Start from finger[1]
timeout_t timeout;
pthread_t auth_thread;
pthread_t enroll_thread;
pthread_mutex_t lock;
}trust_zone_t;
#endif //__FINGERPRINT_COMMON_H_

View file

@ -0,0 +1,735 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2016 The Mokee Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#define LOG_TAG "Fingerprint_tz"
#define LOG_NDEBUG 1
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <dirent.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <cutils/log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include "fingerprint_tz.h"
#include "fp_klte.h"
extern vcs_sensor_t sensor;
trust_zone_t tz;
worker_state_t get_tz_state() {
worker_state_t state;
pthread_mutex_lock(&tz.lock);
state = tz.state;
pthread_mutex_unlock(&tz.lock);
return state;
}
void set_tz_state(worker_state_t state) {
pthread_mutex_lock(&tz.lock);
tz.state = state;
pthread_mutex_unlock(&tz.lock);
}
/*
* cmd: vendorUpdateCalData
*/
int vcs_update_cal_data() {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_vendor_cmd_t *send_vendor_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_vendor_cmd_t)));
memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_vendor_cmd->cmd = vfmVendorDefinedOperation;
send_vendor_cmd->vendor_cmd = vendorUpdateCalData;
resp->data[0] = CALIBRATE_DATA_MAX_LENGTH;
ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret || resp->result) {
ALOGE("Update Cal Data error");
return ret;
}
tz.calibrate_len = resp->data[3] + 0xf;
memcpy(&tz.calibrate_data, &resp->data[2], tz.calibrate_len);
ALOGV("Sended vendorUpdateCalData");
return ret;
}
int vcs_check_state() {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_base_cmd_t *send_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int)));
if (get_tz_state() == STATE_IDLE)
return 1;
if (get_tz_state() == STATE_CANCEL) {
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(int)));
send_cmd->cmd = vfmCaptureAbort;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(int)));
set_tz_state(STATE_IDLE);
return 1;
}
return 0;
}
/*
* cmd: 1.vfmCaptureStart
* 2.vfmCaptureReadData * N
* 3.vfmCaptureProcessData
*/
int vcs_start_capture(void *vdev, time_t t) {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_base_cmd_t *send_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int)));
send_cmd->cmd = vfmCaptureStart;
send_cmd->len = 0x1c;
send_cmd->data[16] = 0x1;
if (t) {
*(time_t*)(&send_cmd->data[20]) = t;
}
send_cmd->data[24] = 0xc0;
send_cmd->data[25] = 0x12;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int)));
if (ret || resp->result) {
ALOGE("Send vfmCaptureStart error");
return ret;
}
vcs_update_cal_data();
pthread_mutex_lock(&sensor.lock);
sensor_capture_start();
pthread_mutex_unlock(&sensor.lock);
pthread_mutex_lock(&sensor.lock);
while ((!vcs_check_state()) && !sensor.signal) {
pthread_cond_wait(&sensor.cond, &sensor.lock);
}
pthread_mutex_unlock(&sensor.lock);
if (vcs_check_state()) {
return -1;
}
pthread_mutex_lock(&sensor.lock);
if (sensor.signal == true) {
sensor.signal = false;
}
pthread_mutex_unlock(&sensor.lock);
while(1) {
if (vcs_check_state()) {
return -1;
}
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(*resp)));
send_cmd->cmd = vfmCaptureReadData;
send_cmd->len = 0x8000;
resp->data[0] = 0xc;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret || resp->result) {
ALOGE("Send vfmCaptureReadData error");
continue;
}
if (resp->data[2] == 2) {
ALOGV("User's finger removed from sensor");
break;
}
//usleep(200000);
}
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_cmd->cmd = vfmCaptureProcessData;
send_cmd->len = 0x1c;
send_cmd->data[16] = 0x1;
*(time_t*)(&send_cmd->data[20]) = time(NULL);
send_cmd->data[24] = 0xc0;
send_cmd->data[25] = 0x12;
resp->data[0] = 0xc;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret) {
ALOGE("Send vfmCaptureProcessData error");
return -1;
}
if (resp->result != 0) {
ALOGE("resp->result=%d",resp->result);
send_acquired_notice(vdev, resp->result);
return vcs_start_capture(vdev, time(NULL));
}
return 0;
}
/*
* cmd: 1.vendorUnknown0
* 2.vcs_start_capture
* 3.vfmMatchImageToTemplates
* 4.vfmPayloadRelease
*/
void* vcs_authenticate(void* vdev) {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_vendor_cmd_t *send_vendor_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_vendor_cmd_t)));
int fingerindex = 0;
int len = 0;
int fake_fid = 0;
memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_vendor_cmd->cmd = vfmVendorDefinedOperation;
send_vendor_cmd->vendor_cmd = vendorUnknown0;
resp->data[0] = 0x4;
ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (resp->result) {
ALOGE("%s:Send vendor unknown 0 cmd error", __FUNCTION__);
}
while (get_tz_state() == STATE_SCAN) {
ret = vcs_start_capture(vdev, 0);
if (ret == -1)
goto out;
trust_zone_5x_cmd_t *send_5x_cmd = NULL;
trust_zone_2x_result_t *resp_2x = NULL;
int idx = 1;
send_5x_cmd = (trust_zone_5x_cmd_t *)handle->ion_sbuffer;
resp_2x = (trust_zone_2x_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_5x_cmd_t)));
memset(send_5x_cmd, 0, QSEECOM_ALIGN(sizeof(*send_5x_cmd)) + QSEECOM_ALIGN(sizeof(*resp_2x)));
send_5x_cmd->cmd = vfmMatchImageToTemplates;
send_5x_cmd->len = 0x14;
send_5x_cmd->unknown[0] = 1;
send_5x_cmd->unknown[1] = 100000;
send_5x_cmd->time_now = time(NULL);
send_5x_cmd->data[0] = 0x1;
send_5x_cmd->data[102388] = vcs_get_enrolled_finger_num();
len = 0;
for (idx = 1; idx <= MAX_NUM_FINGERS; idx++)
if (tz.finger[idx].exist) {
len++;
int address = 102392 + (len - 1) * 15364;
send_5x_cmd->data[address] = 0x45;
send_5x_cmd->data[address + 1] = 0x28;
memcpy(&send_5x_cmd->data[address + 4], &tz.finger[idx].data, FINGER_DATA_MAX_LENGTH);
}
resp_2x->data[0] = 0x5c;
resp_2x->data[25602] = 0x3000;
ret = QSEECom_send_cmd(handle, send_5x_cmd, QSEECOM_ALIGN(sizeof(*send_5x_cmd)), resp_2x, QSEECOM_ALIGN(sizeof(*resp_2x)));
if (ret) {
ALOGE("%s:send vfmMatchImageToTemplates error", __FUNCTION__);
send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS);
goto out;
}
if (resp_2x->result != 0) {
send_acquired_notice(vdev, resp_2x->result);
continue;
}
fake_fid = (int)resp_2x->data[22] + 1;
len = 0;
for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) {
if (tz.finger[idx].exist) {
len++;
if (len == fake_fid) {
fingerindex = idx;
break;
}
}
}
ALOGV("Auth fingerindex=%d", fingerindex);
//memcpy(&tz.finger[fingerindex].data, &resp_2x->data[102419], FINGER_DATA_MAX_LENGTH);
//db_write_to_db(vdev, false, fingerindex);
trust_zone_2x_cmd_t *send_2x_cmd = NULL;
send_2x_cmd = (trust_zone_2x_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_2x_cmd_t)));
memset(send_2x_cmd, 0, QSEECOM_ALIGN(sizeof(*send_2x_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_2x_cmd->cmd = vfmPayloadRelease;
send_2x_cmd->len = PAYLOAD_MAX_LENGTH;
memcpy(&send_2x_cmd->data, &tz.finger[fingerindex].payload, PAYLOAD_MAX_LENGTH);
resp->data[0] = 0x24;
ret = QSEECom_send_cmd(handle, send_2x_cmd, QSEECOM_ALIGN(sizeof(*send_2x_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
break;
}
out:
sensor_uninit();
vcs_uninit();
set_tz_state(STATE_IDLE);
if (fingerindex) {
send_authenticated_notice(vdev, fingerindex);
}
return NULL;
}
/*
* cmd: 1.vfmEnrollBegin
* 2.vendorUnknownA
* 3.vcs_start_capture * 8
* 4.vfmEnrollAddImage
* 5.vfmEnrollFinish
* 6.vfmPayloadBind
* 7.vfmEnrollmentPasswordSet
*/
void* vcs_enroll(void* vdev) {
int count = 8;
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_base_cmd_t *send_cmd = NULL;
trust_zone_vendor_cmd_t *send_vendor_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
int i = 0;
send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer;
send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t)));
int idx = 1;
for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) {
if (!tz.finger[idx].exist) {
break;
}
}
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int)));
send_cmd->cmd = vfmEnrollBegin;
send_cmd->data[102400] = idx;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int)));
if (ret || resp->result) {
ALOGE("send EnrollBegin error");
set_tz_state(STATE_IDLE);
send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS);
return NULL;
}
memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_vendor_cmd->cmd = vfmVendorDefinedOperation;
send_vendor_cmd->vendor_cmd = vendorUnknownA;
resp->data[0] = 0x4;
ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret || resp->result) {
ALOGE("send vendorUnknownA error");
set_tz_state(STATE_IDLE);
send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS);
return NULL;
}
while (get_tz_state() == STATE_ENROLL) {
ret = vcs_start_capture(vdev, 0);
if (ret == -1)
goto out;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(*resp)));
send_cmd->cmd = vfmEnrollAddImage;
resp->data[0] = 0x8;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret) {
ALOGE("%s:send vfmEnrollAddImage error", __FUNCTION__);
set_tz_state(STATE_IDLE);
send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS);
return NULL;
}
if (resp->result != 0) {
send_acquired_notice(vdev, resp->result);
continue;
}
count--;
if (resp->data[2] == 0x1)
count = 0;
if (resp->data[2] != 0x1 && count == 0)
count = 1;
send_enroll_notice(vdev, idx, count);
if (count == 0)
break;
}
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_cmd->cmd = vfmEnrollFinish;
send_cmd->len = AUTH_SESSION_TOKEN_LENGTH;
resp->data[0] = 0x2845;
memcpy(&send_cmd->data, &tz.auth_session_token, AUTH_SESSION_TOKEN_LENGTH);
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret || resp->result) {
ALOGE("Send vfmEnrollFinish error");
}
memcpy(&tz.finger[idx].data, &resp->data[2], FINGER_DATA_MAX_LENGTH);
for (i = 0; i < 2; i++) {
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_cmd->cmd = vfmPayloadBind;
send_cmd->len = 0x1;
send_cmd->zero = 0x7;
sprintf(&send_cmd->data[4], "User_0");
if (i == 1) {
resp->data[0] = 0x50;
}
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
}
if (ret || resp->result) {
ALOGE("Send vfmPayloadBind error");
}
memcpy(&tz.finger[idx].payload, &resp->data[2], PAYLOAD_MAX_LENGTH);
tz.finger[idx].exist = true;
db_write_to_db(vdev, false, idx);
// We may not need to send vfmEnrollmentPasswordSet.
for (i = 0; i < 2; i++) {
trust_zone_3x_cmd_t *send_3x_cmd = NULL;
send_3x_cmd = (trust_zone_3x_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_3x_cmd_t)));
memset(send_3x_cmd, 0, QSEECOM_ALIGN(sizeof(*send_3x_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_3x_cmd->cmd = vfmEnrollmentPasswordSet;
send_3x_cmd->len = AUTH_SESSION_TOKEN_LENGTH;
memcpy(&send_3x_cmd->data, &tz.auth_session_token, AUTH_SESSION_TOKEN_LENGTH);
if (i == 0) {
resp->data[0] = 0x90;
} else {
resp->data[0] = 0x80;
}
ret = QSEECom_send_cmd(handle, send_3x_cmd, QSEECOM_ALIGN(sizeof(*send_3x_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
}
if (ret || resp->result) {
ALOGE("Send vfmEnrollmentPasswordSet error");
}
out:
set_tz_state(STATE_IDLE);
sensor_uninit();
vcs_uninit();
return NULL;
}
void* vcs_timeout(void* vdev) {
struct timeval now;
struct timespec outtime;
int ret = 0;
pthread_mutex_lock(&tz.timeout.lock);
gettimeofday(&now, NULL);
outtime.tv_sec = now.tv_sec + tz.timeout.timeout;
outtime.tv_nsec = now.tv_usec * 1000;
ret = pthread_cond_timedwait(&tz.timeout.cond, &tz.timeout.lock, &outtime);
pthread_mutex_unlock(&tz.timeout.lock);
if (ret == ETIMEDOUT) {
ALOGI("Enroll timeout! Exit!");
int flag = 0;
if (get_tz_state() != STATE_IDLE && get_tz_state() != STATE_CANCEL) {
set_tz_state(STATE_CANCEL);
ioctl(sensor.fd, VFSSPI_IOCTL_SET_DRDY_INT, &flag);
while (1) {
usleep(100000);
if (get_tz_state() == STATE_IDLE)
break;
}
}
send_error_notice(vdev, FINGERPRINT_ERROR_TIMEOUT);
}
return NULL;
}
int vcs_start_authenticate(void *vdev) {
int times = 0;
for (times = 0; times < 5; times++)
if (get_tz_state() != STATE_IDLE) {
ALOGE("%s:Sensor is busy!", __FUNCTION__);
if (times < 4) {
usleep(100000);
continue;
}
return -1;
}
set_tz_state(STATE_SCAN);
int ret = 0;
sensor_init();
ret = vcs_init();
if (ret) return ret;
ret = pthread_create(&tz.auth_thread, NULL, vcs_authenticate, vdev);
if (ret) {
ALOGE("Can't create authenticate thread!!");
}
return ret;
}
int vcs_start_enroll(void *vdev, uint32_t timeout) {
if (get_tz_state() != STATE_IDLE) {
ALOGE("%s:Sensor is busy!", __FUNCTION__);
return -1;
}
set_tz_state(STATE_ENROLL);
int ret = 0;
sensor_init();
ret = vcs_init();
if (ret) {
return ret;
}
ret = pthread_create(&tz.enroll_thread, NULL, vcs_enroll, vdev);
if (ret) {
ALOGE("Can't create enroll thread!!");
return ret;
}
if (timeout) {
tz.timeout.timeout = timeout;
ret = pthread_create(&tz.timeout.timeout_thread, NULL, vcs_timeout, vdev);
if (ret) {
ALOGE("Can't create timeout thread!!");
}
}
return ret;
}
int vcs_get_enrolled_finger_num() {
int num = 0;
int idx = 1;
for (idx = 1; idx <= MAX_NUM_FINGERS; idx++)
if (tz.finger[idx].exist)
num++;
ALOGV("%s: num=%d", __FUNCTION__, num);
return num;
}
/*
* cmd: vendorGetAuthToken
*/
int vcs_update_auth_token() {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_vendor_cmd_t *send_vendor_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_vendor_cmd_t)));
int i = 0;
for (i = 0;i < 2; i++) {
memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_vendor_cmd->cmd = vfmVendorDefinedOperation;
send_vendor_cmd->vendor_cmd = vendorGetAuthToken;
if (i == 1) {
resp->data[0] = 0x80;
}
ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
}
if (resp->result) {
ALOGE("send vendorGetAuthToken failed, qsapp result=%d", resp->result);
return resp->result;
}
memcpy(&tz.auth_token, &resp->data[2], AUTH_TOKEN_LENGTH);
ALOGV("Sended vendorGetAuthToken");
return ret;
}
/*
* cmd: vfmAuthSessionBegin
*/
int vcs_start_auth_session() {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_base_cmd_t *send_cmd = NULL;
trust_zone_vendor_cmd_t *send_vendor_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer;
send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer;
int i = 0;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(*resp)));
send_cmd->cmd = vfmAuthSessionBegin;
resp->data[0] = AUTH_SESSION_TOKEN_LENGTH;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret || resp->result) {
ALOGE("send vfmAuthSessionBegin failed, qsapp result=%d", resp->result);
return ret;
}
memcpy(&tz.auth_session_token, &resp->data[2], AUTH_SESSION_TOKEN_LENGTH);
tz.auth_session_opend = true;
ALOGV("Sended vfmAuthSessionBegin");
return ret;
}
/*
* cmd: vfmAuthSessionEnd
*/
int vcs_stop_auth_session() {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_base_cmd_t *send_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(int)));
send_cmd->cmd = vfmAuthSessionEnd;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(int)));
if (ret || resp->result) {
ALOGE("send vfmAuthSessionEnd failed, qsapp result=%d", resp->result);
}
memset(tz.auth_session_token, 0, AUTH_SESSION_TOKEN_LENGTH);
tz.auth_session_opend = false;
ALOGV("Sended vfmAuthSessionEnd");
return ret;
}
/*
* cmd: 1.vfmInitialize
* 2.vendorEnterAuthSession
* 3.vfmDeviceInitialize
* 4.vfmDeviceCalibrate
*/
int vcs_resume() {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_base_cmd_t *send_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
int ret = 0;
send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t)));
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int)));
send_cmd->cmd = vfmInitialize;
send_cmd->len = 4;
send_cmd->data[0] = 2;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int)));
if (ret || resp->result) {
ALOGE("send vfmInitialize failed, qsapp result=%d", resp->result);
return ret;
}
ALOGV("Sended vfmInitialize");
if (tz.auth_session_opend) {
trust_zone_vendor_cmd_t *send_vendor_cmd = NULL;
send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer;
memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_vendor_cmd->cmd = vfmVendorDefinedOperation;
send_vendor_cmd->vendor_cmd = vendorEnterAuthSession;
send_vendor_cmd->len = 0x70;
memcpy(&send_vendor_cmd->data, &tz.auth_token, 0x70);
ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret || resp->result) {
ALOGE("send EnterAuthSession failed, qsapp result=%d", resp->result);
return resp->result;
}
}
ALOGV("Sended EnterAuthSession");
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int)));
send_cmd->cmd = vfmDeviceInitialize;
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int)));
if (ret || resp->result) {
ALOGE("send vfmDeviceInitialize failed, qsapp result=%d", resp->result);
return ret;
}
ALOGV("Sended vfmDeviceInitialize");
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp)));
send_cmd->cmd = vfmDeviceCalibrate;
send_cmd->data[0] = 0xc0;
send_cmd->data[1] = 0x12;
resp->data[0] = CALIBRATE_DATA_MAX_LENGTH;
if (tz.calibrate_len) {
send_cmd->len = tz.calibrate_len;
memcpy(&send_cmd->data[4], &tz.calibrate_data, tz.calibrate_len);
} else {
send_cmd->len = 0x10;
}
ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp)));
if (ret || resp->result) {
ALOGE("send vfmDeviceCalibrate failed, qsapp result=%d", resp->result);
return ret;
}
if (tz.calibrate_len == 0) {
tz.calibrate_len = resp->data[3] + 0xf;
memcpy(&tz.calibrate_data, &resp->data[2], tz.calibrate_len);
}
ALOGV("Sended vfmDeviceCalibrate");
return ret;
}
/*
* cmd: vfmUninitialize
* set bandwidth to low and shutdown app
*/
int vcs_uninit() {
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
trust_zone_base_cmd_t *send_cmd = NULL;
trust_zone_normal_result_t *resp = NULL;
send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer;
resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t)));
if (tz.auth_session_opend) {
vcs_update_auth_token();
}
memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(int)));
send_cmd->cmd = vfmUninitialize;
QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(int)));
QSEECom_set_bandwidth(handle, false);
QSEECom_shutdown_app((struct QSEECom_handle **)&tz.qhandle);
tz.init = false;
set_tz_state(STATE_IDLE);
ALOGV("Closed securefp qsapp");
return 0;
}
/*
* start app and set bandwidth to high
* Call vcs_resume
*/
int vcs_init() {
int ret = 0;
if (tz.init) {
ALOGI("securefp qsapp is already running!");
return ret;
}
ret = QSEECom_start_app((struct QSEECom_handle **)&tz.qhandle,
"/firmware/image", "securefp", SB_LENGTH);
if (ret) {
ALOGE("Loading securefp app failed");
return -1;
}
struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle);
ret = QSEECom_set_bandwidth(handle, true);
if (ret) {
ALOGE("Set bandwidth failed");
return -1;
}
tz.init = true;
ALOGV("securefp qsapp init success!");
ret = vcs_resume();
return ret;
}

View file

@ -0,0 +1,136 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2016 The Mokee Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#ifndef __FINGERPRINT_TZ_H_
#define __FINGERPRINT_TZ_H_
#include "fingerprint_common.h"
#include "QSEEComAPI.h"
/* QSEE cmd */
typedef enum trust_zone_cmd_id_t {
vfmProvision = 0x1,
vfmInitialize = 0x2,
vfmUninitialize = 0x3,
vfmDeviceInitialize = 0x4,
vfmDeviceCalibrate = 0x5,
vfmAuthSessionBegin = 0x6,
vfmAuthSessionEnd = 0x7,
vfmCaptureStart = 0x8,
vfmCaptureReadData = 0x9,
vfmCaptureProcessData = 0xa,
vfmCaptureAbort = 0xb,
vfmCaptureGetStatus = 0xc,
/* QSEE cmd id 0xd is unused. */
vfmCaptureFlushImage = 0xe,
vfmEnrollBegin = 0xf,
vfmEnrollAddImage = 0x10,
vfmEnrollFinish = 0x11,
vfmEnrollmentPasswordSet = 0x12,
vfmEnrollmentPasswordVerify = 0x13,
vfmMatchImageToTemplates = 0x14,
vfmPayloadBind = 0x15,
vfmPayloadRelease = 0x16,
vfmVendorDefinedOperation = 0x17
}trust_zone_cmd_id_t;
typedef enum trust_zone_vendor_cmd_id_t {
vendorUnknown0 = 0x0,
vendorGetVersion = 0x1,//0x10
vendorUnknownA = 0xa,
vendorGetAuthToken = 0x14,
vendorEnterAuthSession = 0x15,
vendorUpdateCalData = 0x17
}trust_zone_vendor_cmd_id_t;
typedef struct trust_zone_normal_cmd_t {
trust_zone_cmd_id_t cmd;
int len;
int zero;
char data[BUFFER_LENGTH - 12];
}trust_zone_base_cmd_t;
typedef struct trust_zone_vendor_cmd_t {
trust_zone_cmd_id_t cmd;
trust_zone_vendor_cmd_id_t vendor_cmd;
int len;
int zero;
char data[BUFFER_LENGTH - 16];
}trust_zone_vendor_cmd_t;
typedef struct trust_zone_2x_cmd_t {
trust_zone_cmd_id_t cmd;
int len;
int zero;
char data[BUFFER_LENGTH * 2 - 12];
}trust_zone_2x_cmd_t;
typedef struct trust_zone_3x_cmd_t {
trust_zone_cmd_id_t cmd;
int len;
int zero;
char data[BUFFER_LENGTH * 3 - 12];
}trust_zone_3x_cmd_t;
typedef struct trust_zone_5x_cmd_t { //only use on vfmMatchImageToTemplates
trust_zone_cmd_id_t cmd;
int len;
int zero;
int unknown[2];
time_t time_now;
char data[563304];
}trust_zone_5x_cmd_t;
typedef struct trust_zone_normal_result_t {
int zero;
int result;
int data[BUFFER_LENGTH/4 - 2];
}trust_zone_normal_result_t;
typedef struct trust_zone_2x_result_t {
int zero;
int result;
int data[(BUFFER_LENGTH * 2)/4 - 2];
}trust_zone_2x_result_t;
#define FINGERPRINT_ERROR_HW_UNAVAILABLE (1)
#define FINGERPRINT_ERROR_UNABLE_TO_PROCESS (2)
#define FINGERPRINT_ERROR_TIMEOUT (3)
#define FINGERPRINT_ERROR_NO_SPACE (4)
#define FINGERPRINT_ERROR_CANCELED (5)
#define FINGERPRINT_ERROR_UNABLE_TO_REMOVE (6)
#define FINGERPRINT_ERROR_VENDOR_BASE (1000)
worker_state_t get_tz_state();
void set_tz_state(worker_state_t state);
int vcs_update_cal_data();
int vcs_check_state();
int vcs_start_capture();
void* vcs_authenticate(void* vdev);
void* vcs_enroll(void* vdev);
int vcs_start_authenticate(void *vdev);
int vcs_start_enroll(void *vdev, uint32_t timeout);
int vcs_get_enrolled_finger_num();
int vcs_update_auth_token();
int vcs_start_auth_session();
int vcs_stop_auth_session();
int vcs_resume();
int vcs_uninit();
int vcs_init();
#endif /* __FINGERPRINT_TZ_H_ */

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2014 The Android Open Source Project * Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The CyanogenMod Project * Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2016 The Mokee Project * Copyright (C) 2016 The Mokee Project
* *
@ -16,101 +16,30 @@
* limitations under the License. * limitations under the License.
*/ */
#include <hardware/hardware.h> #include "fingerprint_common.h"
#include <hardware/fingerprint.h> #include "vfs61xx_ioctl.h"
#define CALL_BASE 0 #define FINGER_DATABASE_FILENAME "/data/validity/finger.db"
#define SAMSUNG_FP_DB_PATH "/data/validity/template.db"
#define SENSOR_FILE_NAME "/dev/vfsspi"
#define MAX_DATABASE_CMD 255
#define CALL_INITSERVICE 1 int sensor_uninit();
#define CALL_ENROLL 2 int sensor_init();
//userId ,fingerIndex void sensor_process_signal(int signum);
#define CALL_CANCEL 3 int sensor_register();
#define CALL_REMOVE 4 int sensor_capture_start();
//userId ,fingerIndex
#define CALL_IDENTIFY 5
//userId
#define CALL_GET_ENROLLED_FINGER_LIST 6
//userId
#define CALL_CLEANUP 7
typedef enum worker_state_t { int db_check_and_create_table(void* device);
STATE_IDLE = 0, int db_read_to_tz(void *device);
STATE_ENROLL, int db_write_to_db(void *device, bool remove, int fid);
STATE_SCAN, int db_init(void *device);
STATE_EXIT int db_uninit(void *device);
} worker_state_t;
typedef struct worker_thread_t { void send_error_notice(void* device, int error_info_int);
pthread_t thread; void send_acquired_notice(void* device, int acquired_ret);
worker_state_t state; void send_enroll_notice(void *device, int fid, int remaining);
} worker_thread_t; void send_authenticated_notice(void *device, int fid);
void send_remove_notice(void *device, int fid);
typedef struct vcs_fingerprint_device_t {
fingerprint_device_t device; // "inheritance"
worker_thread_t listener;
uint64_t op_id;
uint64_t challenge;
uint64_t user_id;
uint64_t group_id;
uint64_t secure_user_id;
uint64_t authenticator_id;
uint32_t active_gid;
int send_fd; //send to validity service
int receive_fd; //recevie from validity service
bool init;
pthread_mutex_t lock;
} vcs_fingerprint_device_t;
static __inline__ int fd_write(int fd, const void* buff, int len){
int len2;
do {
len2 = write(fd, buff, len);
} while (len2 < 0 && errno == EINTR);
return len2;
}
static __inline__ int fd_read(int fd, void* buff, int len){
int len2;
do {
len2 = read(fd, buff, len);
} while (len2 < 0 && errno == EINTR);
return len2;
}
static void checkinit(vcs_fingerprint_device_t* vdev);
static int sendcommand(vcs_fingerprint_device_t* vdev, uint8_t* command, int num);
static int getfingermask(vcs_fingerprint_device_t* vdev);
static int initService(vcs_fingerprint_device_t* vdev);
static void send_error_notice(vcs_fingerprint_device_t* vdev, fingerprint_error_t error_info);
static void send_acquired_notice(vcs_fingerprint_device_t* vdev, fingerprint_acquired_info_t acquired_info);
static void send_enroll_notice(vcs_fingerprint_device_t* vdev, int fid, int remaining);
static void send_authenticated_notice(vcs_fingerprint_device_t* vdev, int fid);
static void send_remove_notice(vcs_fingerprint_device_t* vdev, int fid);
static uint64_t get_64bit_rand();
static uint64_t fingerprint_get_auth_id(struct fingerprint_device* device);
static int fingerprint_set_active_group(struct fingerprint_device *device, uint32_t gid,
const char __unused *path);
static int fingerprint_authenticate(struct fingerprint_device *device,
uint64_t operation_id, __unused uint32_t gid);
static int fingerprint_enroll(struct fingerprint_device *device,
const hw_auth_token_t *hat,
uint32_t __unused gid,
uint32_t __unused timeout_sec);
static uint64_t fingerprint_pre_enroll(struct fingerprint_device *device);
static int fingerprint_post_enroll(struct fingerprint_device* device);
static int fingerprint_cancel(struct fingerprint_device *device);
static int fingerprint_enumerate(struct fingerprint_device *device,
fingerprint_finger_id_t *results, uint32_t *max_size);
static int fingerprint_remove(struct fingerprint_device *device,
uint32_t __unused gid, uint32_t fid);
static int set_notify_callback(struct fingerprint_device *device,
fingerprint_notify_t notify);
static worker_state_t getListenerState(vcs_fingerprint_device_t* dev);
static void* listenerSocket(void* data);
static int fingerprint_close(hw_device_t* device);
static int fingerprint_open(const hw_module_t* module, const char __unused *id,
hw_device_t** device);

206
fingerprint/hash.c Normal file
View file

@ -0,0 +1,206 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2016 The Mokee Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <string.h>
#include "hash.h"
SHA1Context sha;
/*
* HASH method: SHA1
*/
uint64_t convert_hash_to_number() {
uint64_t num = 0;
num = ((uint64_t)sha.Message_Digest[0] << 32) + sha.Message_Digest[1];
return num;
}
uint64_t hash_file(const char *file_path) {
FILE * file;
char str[MAX_FILE_LENGTH];
int len = 0;
file = fopen(file_path, "rb");
if (!file)
return 1;
len = fread(str, sizeof(char), MAX_FILE_LENGTH, file);
fclose(file);
sha1_hash(str, len);
return convert_hash_to_number();
}
uint64_t hash_string(const char *str) {
sha1_hash(str, strlen(str));
return convert_hash_to_number();
}
void SHA1Reset(SHA1Context *context){
context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;
context->Message_Digest[0] = 0x67452301;
context->Message_Digest[1] = 0xEFCDAB89;
context->Message_Digest[2] = 0x98BADCFE;
context->Message_Digest[3] = 0x10325476;
context->Message_Digest[4] = 0xC3D2E1F0;
context->Computed = 0;
context->Corrupted = 0;
}
int SHA1Result(SHA1Context *context){
if (context->Corrupted) {
return 0;
}
if (!context->Computed) {
SHA1PadMessage(context);
context->Computed = 1;
}
return 1;
}
void SHA1Input(SHA1Context *context,const char *message_array,unsigned length){
if (!length) return;
if (context->Computed || context->Corrupted){
context->Corrupted = 1;
return;
}
while(length-- && !context->Corrupted){
context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
context->Length_Low += 8;
context->Length_Low &= 0xFFFFFFFF;
if (context->Length_Low == 0){
context->Length_High++;
context->Length_High &= 0xFFFFFFFF;
if (context->Length_High == 0) context->Corrupted = 1;
}
if (context->Message_Block_Index == 64){
SHA1ProcessMessageBlock(context);
}
message_array++;
}
}
void SHA1ProcessMessageBlock(SHA1Context *context){
const unsigned K[] = {0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
int t;
unsigned temp;
unsigned W[80];
unsigned A, B, C, D, E;
for(t = 0; t < 16; t++) {
W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
}
for(t = 16; t < 80; t++) W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
A = context->Message_Digest[0];
B = context->Message_Digest[1];
C = context->Message_Digest[2];
D = context->Message_Digest[3];
E = context->Message_Digest[4];
for(t = 0; t < 20; t++) {
temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 20; t < 40; t++) {
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 40; t < 60; t++) {
temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 60; t < 80; t++) {
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;
context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;
context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;
context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;
context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;
context->Message_Block_Index = 0;
}
void SHA1PadMessage(SHA1Context *context){
if (context->Message_Block_Index > 55) {
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 64) context->Message_Block[context->Message_Block_Index++] = 0;
SHA1ProcessMessageBlock(context);
while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0;
} else {
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0;
}
context->Message_Block[56] = (context->Length_High >> 24 ) & 0xFF;
context->Message_Block[57] = (context->Length_High >> 16 ) & 0xFF;
context->Message_Block[58] = (context->Length_High >> 8 ) & 0xFF;
context->Message_Block[59] = (context->Length_High) & 0xFF;
context->Message_Block[60] = (context->Length_Low >> 24 ) & 0xFF;
context->Message_Block[61] = (context->Length_Low >> 16 ) & 0xFF;
context->Message_Block[62] = (context->Length_Low >> 8 ) & 0xFF;
context->Message_Block[63] = (context->Length_Low) & 0xFF;
SHA1ProcessMessageBlock(context);
}
int sha1_hash(const char *source, int len){
SHA1Reset(&sha);
SHA1Input(&sha, source, len);
if (!SHA1Result(&sha)){
return -1;
}
return 0;
}

47
fingerprint/hash.h Normal file
View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2016 The Mokee Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __HASH_H_
#define __HASH_H_
#define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits))))
#define MAX_FILE_LENGTH (300000)
typedef struct SHA1Context{
unsigned Message_Digest[5];
unsigned Length_Low;
unsigned Length_High;
unsigned char Message_Block[64];
int Message_Block_Index;
int Computed;
int Corrupted;
} SHA1Context;
void SHA1Reset(SHA1Context *);
int SHA1Result(SHA1Context *);
void SHA1Input( SHA1Context *,const char *,unsigned);
void SHA1ProcessMessageBlock(SHA1Context *);
void SHA1PadMessage(SHA1Context *);
int sha1_hash(const char *source, int len);
uint64_t hash_file(const char *file_path);
uint64_t hash_string(const char *str);
#endif //__HASH_H_

115
fingerprint/vfs61xx_ioctl.h Normal file
View file

@ -0,0 +1,115 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Copied from kernel - drivers/fingerprint/vfs61xx.h
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VFS61XX_IOCTL_H_
#define VFS61XX_IOCTL_H_
/* See kernel/include/linux/fprint_secure.h */
#ifndef ENABLE_SENSORS_FPRINT_SECURE
#define ENABLE_SENSORS_FPRINT_SECURE
#endif
#include <linux/ioctl.h>
/* Pass to VFSSPI_IOCTL_REGISTER_DRDY_SIGNAL command */
struct vfsspi_iocRegSignal {
/* Process ID to which SPI driver sends signal
* indicating that DRDY is asserted */
int userPID;
int signalID; /* Signal number */
};
/* Magic number of IOCTL command */
#define VFSSPI_IOCTL_MAGIC 'k'
/*
* IOCTL commands definitions
*/
#ifndef ENABLE_SENSORS_FPRINT_SECURE
/* Transmit data to the device
and retrieve data from it simultaneously */
#define VFSSPI_IOCTL_RW_SPI_MESSAGE \
_IOWR(VFSSPI_IOCTL_MAGIC, 1, unsigned int)
#endif
/* Hard reset the device */
#define VFSSPI_IOCTL_DEVICE_RESET \
_IO(VFSSPI_IOCTL_MAGIC, 2)
/* Set the baud rate of SPI master clock */
#define VFSSPI_IOCTL_SET_CLK \
_IOW(VFSSPI_IOCTL_MAGIC, 3, unsigned int)
#ifndef ENABLE_SENSORS_FPRINT_SECURE
/* Get level state of DRDY GPIO */
#define VFSSPI_IOCTL_CHECK_DRDY \
_IO(VFSSPI_IOCTL_MAGIC, 4)
#endif
/* Register DRDY signal. It is used by SPI driver
* for indicating host that DRDY signal is asserted. */
#define VFSSPI_IOCTL_REGISTER_DRDY_SIGNAL \
_IOW(VFSSPI_IOCTL_MAGIC, 5, unsigned int)
/* Store the user data into the SPI driver. Currently user data is a
* device info data, which is obtained from announce packet. */
#ifndef ENABLE_SENSORS_FPRINT_SECURE
#define VFSSPI_IOCTL_SET_USER_DATA \
_IOW(VFSSPI_IOCTL_MAGIC, 6, unsigned int)
#endif
#ifndef ENABLE_SENSORS_FPRINT_SECURE
/* Retrieve user data from the SPI driver*/
#define VFSSPI_IOCTL_GET_USER_DATA \
_IOWR(VFSSPI_IOCTL_MAGIC, 7, unsigned int)
#endif
/* Enable/disable DRDY interrupt handling in the SPI driver */
#define VFSSPI_IOCTL_SET_DRDY_INT \
_IOW(VFSSPI_IOCTL_MAGIC, 8, unsigned int)
/* Put device in Low power mode */
#define VFSSPI_IOCTL_DEVICE_SUSPEND \
_IO(VFSSPI_IOCTL_MAGIC, 9)
#ifndef ENABLE_SENSORS_FPRINT_SECURE
/* Indicate the fingerprint buffer size for read */
#define VFSSPI_IOCTL_STREAM_READ_START \
_IOW(VFSSPI_IOCTL_MAGIC, 10, unsigned int)
/* Indicate that fingerprint acquisition is completed */
#define VFSSPI_IOCTL_STREAM_READ_STOP \
_IO(VFSSPI_IOCTL_MAGIC, 11)
/* Retrieve supported SPI baud rate table */
#define VFSSPI_IOCTL_GET_FREQ_TABLE \
_IOWR(VFSSPI_IOCTL_MAGIC, 12, unsigned int)
#endif
/* Turn on the power to the sensor */
#define VFSSPI_IOCTL_POWER_ON \
_IO(VFSSPI_IOCTL_MAGIC, 13)
/* Turn off the power to the sensor */
#define VFSSPI_IOCTL_POWER_OFF \
_IO(VFSSPI_IOCTL_MAGIC, 14)
#ifdef ENABLE_SENSORS_FPRINT_SECURE
/* To disable spi core clock */
#define VFSSPI_IOCTL_DISABLE_SPI_CLOCK \
_IO(VFSSPI_IOCTL_MAGIC, 15)
/* To set SPI configurations like gpio, clks */
#define VFSSPI_IOCTL_SET_SPI_CONFIGURATION \
_IO(VFSSPI_IOCTL_MAGIC, 16)
/* To reset SPI configurations */
#define VFSSPI_IOCTL_RESET_SPI_CONFIGURATION \
_IO(VFSSPI_IOCTL_MAGIC, 17)
#endif
/* get sensor orienation from the SPI driver*/
#define VFSSPI_IOCTL_GET_SENSOR_ORIENT \
_IOR(VFSSPI_IOCTL_MAGIC, 18, unsigned int)
#endif /* VFS61XX_IOCTL_H_ */

View file

@ -76,8 +76,7 @@ PRODUCT_PACKAGES += \
# Fingerprint # Fingerprint
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
fingerprintd \ fingerprintd \
fingerprint.msm8974 \ fingerprint.msm8974
ValidityService
# Gello # Gello
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \

View file

@ -1074,12 +1074,6 @@ service sec-sh /system/bin/sh /system/etc/init.sec.boot.sh
user root user root
oneshot oneshot
# SENSOR FRAMEWORK : starts fingerprintService
service vcsFPService /system/bin/vcsFPService
class late_start
user system
group system
on property:persist.sys.ssr.restart_level=1 on property:persist.sys.ssr.restart_level=1
write /sys/module/subsystem_restart/parameters/restart_level 1 write /sys/module/subsystem_restart/parameters/restart_level 1

View file

@ -20,7 +20,6 @@
/dev/block/platform/msm_sdcc.1/by-name/efs u:object_r:modem_efs_partition_device:s0 /dev/block/platform/msm_sdcc.1/by-name/efs u:object_r:modem_efs_partition_device:s0
# Fingerprint # Fingerprint
/system/bin/vcsFPService u:object_r:vcs_exec:s0
/data/validity(/.*)? u:object_r:vcs_data_file:s0 /data/validity(/.*)? u:object_r:vcs_data_file:s0
/dev/validity(/.*)? u:object_r:vcs_device:s0 /dev/validity(/.*)? u:object_r:vcs_device:s0
/dev/vfsspi u:object_r:vcs_device:s0 /dev/vfsspi u:object_r:vcs_device:s0

View file

@ -1 +1,13 @@
allow fingerprintd system_app:unix_stream_socket { connectto read write setopt }; allow fingerprintd vcs_data_file:dir create_dir_perms;
allow fingerprintd vcs_data_file:file create_file_perms;
allow fingerprintd vcs_device:dir create_dir_perms;
allow fingerprintd vcs_device:file create_file_perms;
allow fingerprintd vcs_device:fifo_file create_file_perms;
allow fingerprintd vcs_device:chr_file create_file_perms;
allow fingerprintd tee_device:chr_file rw_file_perms;
allow fingerprintd firmware_file:dir r_dir_perms;
allow fingerprintd firmware_file:file r_file_perms;

View file

@ -1,7 +0,0 @@
# For com.validity.fingerprint
allow system_app vcs:process signull;
allow system_app vcs_data_file:dir r_dir_perms;
allow system_app vcs_data_file:file r_file_perms;
allow system_app vcs_device:dir r_dir_perms;
allow system_app vcs_device:file r_file_perms;
allow system_app vcs_device:fifo_file create_file_perms;

View file

@ -1,22 +0,0 @@
type vcs, domain;
type vcs_exec, exec_type, file_type;
# vcs
init_daemon_domain(vcs)
binder_use(vcs)
allow vcs system_app:process signull;
allow vcs vcs_data_file:dir create_dir_perms;
allow vcs vcs_data_file:file create_file_perms;
allow vcs vcs_device:dir create_dir_perms;
allow vcs vcs_device:file create_file_perms;
allow vcs vcs_device:fifo_file create_file_perms;
allow vcs vcs_device:chr_file create_file_perms;
allow vcs tee_device:chr_file rw_file_perms;
allow vcs firmware_file:dir r_dir_perms;
allow vcs firmware_file:file r_file_perms;

View file

@ -1,33 +0,0 @@
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := ValidityService
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_AAPT_FLAGS := --auto-add-overlay
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_JACK_ENABLED := disabled
include $(BUILD_PACKAGE)

View file

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.validity.fingerprint"
coreApp="true"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
<application
android:name=".ValidityServiceStarter"
android:allowBackup="true"
android:icon="@drawable/icon"
android:persistent="true"
android:label="@string/app_name">
<service android:name=".ValidityService"
android:exported="true" />
</application>
</manifest>

View file

@ -1,2 +0,0 @@
-verbose
-keep class com.validity.fingerprint.* {*;}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The CyanogenMod Project
Copyright (C) 2016 The Mokee Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Validity service</string>
</resources>

View file

@ -1,32 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class ConsumerInfo {
public Object info;
public int type;
public ConsumerInfo() {
}
public ConsumerInfo(int type) {
this.type = type;
}
}

View file

@ -1,32 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class EnrollCaptureStatus {
public int badSwipes;
public int cumulativeCoverageMap;
public int currentCoverageMap;
public int imageQuality;
public int positionFeedback;
public int progress;
public int templateResult;
public int totalSwipes;
}

View file

@ -1,30 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class EnrollUser {
public int fingerIndex;
public int mode;
public String userId;
public EnrollUser() {
mode = 1;
}
}

View file

@ -1,211 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
import android.content.Context;
import android.util.Log;
public class Fingerprint extends FingerprintCore {
public static final int VCS_ENROLL_MODE_DEFAULT = 1;
public static final int VCS_ENROLL_MODE_REENROLL = 2;
public static final int VCS_ENROLL_MODE_SECONDARY = 3;
public static final int VCS_FINGER_POSITION_FEEDBACK_SWIPE_MIDDLE = 11;
public static final int VCS_FINGER_POSITION_FEEDBACK_SWIPE_MIDDLE_FULL = 12;
public static final int VCS_FINGER_POSITION_FEEDBACK_SWIPE_LEFT = 21;
public static final int VCS_FINGER_POSITION_FEEDBACK_SWIPE_RIGHT = 31;
public static final int VCS_FINGER_POSITION_FEEDBACK_SWIPE_ANY = 41;
public static final int VCS_NOTIFY_SNSR_TEST_CONTINUE = 1;
public static final int VCS_NOTIFY_SNSR_TEST_STOP = 2;
public static final int VCS_NOTIFY_ENROLL_BEGIN = 3;
public static final int VCS_NOTIFY_ENROLL_END = 4;
public static final int VCS_REQUEST_PROCESS_FIDO = 1;
public static final int VCS_REQUEST_PROCESS_ALIPAY = 2;
public static final int VCS_REQUEST_COMMAND_SENSOR_TEST = 11;
public static final int VCS_REQUEST_GET_SENSOR_INFO = 12;
public static final int VCS_REQUEST_GET_ENROLL_REPEAT_COUNT = 13;
private static final int VCS_REQUEST_ENABLE_WOF = 21;
private static final int VCS_REQUEST_GET_WOF_STATE = 22;
public static final int VCS_SENSOR_STATUS_OK = 0;
public static final int VCS_SENSOR_STATUS_WORKING = 46;
public static final int VCS_SENSOR_STATUS_INITIALISING = 358;
public static final int VCS_SENSOR_STATUS_INITIALIZING = 358;
public static final int VCS_SENSOR_STATUS_OUT_OF_ORDER = 360;
public static final int VCS_SENSOR_STATUS_MALFUNCTIONED = 534;
public static final int VCS_SENSOR_STATUS_FAILURE = 535;
public static final int VCS_WOF_STATE_INACTIVE = 0;
public static final int VCS_WOF_STATE_ACTIVE = 1;
private native int jniEnableSensorDevice(int enable);
private native int jniEnrollUser(Object enrollInfo);
private native int jniEnrollUser(String userId, int fingerIndex, int mode);
private native int jniEnrollUser(String userId, String appData, int fingerIndex);
private native int jniGetSensorStatus();
private native int jniNotify(int code, Object data);
private native int jniProcessFIDO(byte requestData[], VcsByteArray responseData);
private native int jniReEnrollUser(String userId, String appData, int fingerIndex, int mode);
private native int jniRemoveEnrolledFinger(Object enrollInfo);
private native int jniRemoveEnrolledFinger(String userId, int fingerIndex);
private native int jniRequest(int command, Object data);
private native int jniSetPassword(String userId, byte abyte0[], byte newPwdHash[]); // What is abyte0 means?
private native int jniVerifyPassword(String userId, byte pwdHash[]);
public Fingerprint(Context ctx) {
super(ctx);
}
public Fingerprint(Context ctx, FingerprintCore.EventListener listener) {
super(ctx, listener);
}
public int enableSensorDevice(boolean enable) {
if (mOperation != 150)
return VCS_RESULT_ALREADY_INPROGRESS;
return jniEnableSensorDevice((enable? 1: 0));
}
public int enableWakeOnFinger() {
return jniRequest(VCS_REQUEST_ENABLE_WOF, null);
}
public int enroll(EnrollUser enrollInfo) {
int ret = VCS_RESULT_FAILED;
if (mOperation != 150)
return ret;
ret = jniEnrollUser(enrollInfo);
if (ret == VCS_RESULT_OK)
mOperation = 151;
return ret;
}
public int enroll(String userId, int fingerIndex) {
int ret = VCS_RESULT_FAILED;
if (mOperation != 150)
return ret;
if (null == userId)
userId = "";
ret = jniEnrollUser(userId, fingerIndex, VCS_ENROLL_MODE_DEFAULT);
if (ret == VCS_RESULT_OK)
mOperation = 151;
return ret;
}
public int enroll(String userId, int fingerIndex, int mode) {
int ret = VCS_RESULT_FAILED;
if (mOperation != 150)
return ret;
if (null == userId)
userId = "";
ret = jniEnrollUser(userId, fingerIndex, mode);
if (ret == VCS_RESULT_OK)
mOperation = 151;
return ret;
}
public int enroll(String userId, String appData, int fingerIndex) {
int ret = VCS_RESULT_FAILED;
if (mOperation != 150)
return ret;
if (null == userId)
userId = "";
if (null == appData)
appData = "";
ret = jniEnrollUser(userId, appData, fingerIndex);
if (ret == VCS_RESULT_OK)
mOperation = 151;
return ret;
}
public int enroll(String userId, String appData, int fingerIndex, int mode) {
int ret = VCS_RESULT_FAILED;
if (mOperation != 150)
return ret;
if (null == userId)
userId = "";
if (null == appData)
appData = "";
ret = jniReEnrollUser(userId, appData, fingerIndex, mode);
if (ret == VCS_RESULT_OK)
mOperation = 151;
return ret;
}
public int getSensorStatus() {
if (mOperation != 150)
return VCS_RESULT_ALREADY_INPROGRESS;
return jniGetSensorStatus();
}
public int getWakeOnFingerState(VcsInt wofState) {
if (wofState == null)
return VCS_RESULT_INVALID_ARGUMENT;
return jniRequest(VCS_REQUEST_GET_WOF_STATE, wofState);
}
public int notify(int code, Object data) {
return jniNotify(code, data);
}
public int processFIDO(byte requestData[], VcsByteArray responseData) {
if ((requestData == null) || (responseData == null))
return VCS_RESULT_INVALID_ARGUMENT;
return jniProcessFIDO(requestData, responseData);
}
public int removeEnrolledFinger(RemoveEnroll enrollInfo) {
return jniRemoveEnrolledFinger(enrollInfo);
}
public int removeEnrolledFinger(String userId, int fingerIndex) {
if (mOperation != 150)
return VCS_RESULT_ALREADY_INPROGRESS;
if (null == userId)
userId = "";
return jniRemoveEnrolledFinger(userId, fingerIndex);
}
public int removeEnrolledUser(String userId) {
if (mOperation != 150)
return VCS_RESULT_ALREADY_INPROGRESS;
if (null == userId)
userId = "";
return jniRemoveEnrolledFinger(userId, FINGER_INDEX_LEFT_THUMB_SECOND);
}
public int request(int command, Object data) {
return jniRequest(command, data);
}
public int setPassword(String userId, byte newPwdHash[]) {
if (userId == null || newPwdHash == null)
return VCS_RESULT_INVALID_ARGUMENT;
return jniSetPassword(userId, "".getBytes(), newPwdHash);
}
public int verifyPassword(String userId, byte pwdHash[]) {
if (userId == null || pwdHash == null)
return VCS_RESULT_INVALID_ARGUMENT;
return jniVerifyPassword(userId, pwdHash);
}
}

View file

@ -1,26 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
import android.graphics.Bitmap;
public class FingerprintBitmap {
public Bitmap fingerprint;
public int quality;
}

View file

@ -1,230 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
import android.content.Context;
import android.util.Log;
public class FingerprintCore extends VcsEvents {
public static interface EventListener {
public abstract void onEvent(FingerprintEvent fingerprintevent);
}
public static final String API_VERSION = "0.7";
public static final String VCS_POLICY_VERSION = "0.1";
protected static final boolean DBG = false;
protected static final int IDLE = 150;
protected static final int ENROLL = 151;
protected static final int IDENTIFY = 152;
protected static final int STOREDATATOUSER = 153;
protected static final int GETDATAFROMUSER = 154;
protected static final int REMOVEDATAFROMUSER = 155;
protected static final int GETPRINT = 156;
protected static final String TAG = "Fingerprint";
protected static final String USER_ID = "android";
protected int mOperation;
private EventListener mEventListener;
private String mAppId;
private String mUserId;
private String mAppKey;
private String mKeyData;
private native int jniCancelOp();
private native int jniCleanupVcs();
private native int jniGetEnrolledFingerList(String userId, VcsInt fingermask);
private native int jniGetFingerprintImage();
private native int jniGetFingerprintImageEx(Object info);
private native String[] jniGetUserList(VcsInt retCode);
private native String jniGetVersion();
private native int jniIdentify(String userId);
private native int jniInitVcs();
private native int jniInitVcs(FingerprintCore fingerprintcore);
private native int jniProtect(byte toProtect[], VcsAddInfo addInfo, VcsByteArray protectedData);
private native int jniRegisterEventsCB(FingerprintCore fingerprintcore);
private native int jniSetDetectFinger(int timeout);
private native int jniSetSecurityLevel(int level);
private native int jniUnprotect(byte protectedData[], VcsAddInfo addInfo, VcsByteArray unProtectedData);
static {
try {
System.loadLibrary("vcsfp");
}
catch (Throwable e) {
Log.e("Fingerprint", "Error loading library libvcsfp: " + e);
}
}
public FingerprintCore(Context ctx) {
mOperation = IDLE;
mEventListener = null;
mAppId = "";
mUserId = "";
mAppKey = "";
mKeyData = "";
jniInitVcs(this);
}
public FingerprintCore(Context ctx, EventListener listener) {
mOperation = IDLE;
mEventListener = null;
mAppId = "";
mUserId = "";
mAppKey = "";
mKeyData = "";
VLog.i("init ret="+jniInitVcs(this));
mEventListener = listener;
}
private boolean isOperationComplete(int eventId) {
if (eventId == VCS_EVT_ENROLL_SUCCESS || eventId == VCS_EVT_IDENTIFY_SUCCESS ||
eventId == VCS_EVT_VERIFY_SUCCESS || eventId == VCS_EVT_ENROLL_FAILED ||
eventId == VCS_EVT_IDENTIFY_FAILED || eventId == VCS_EVT_VERIFY_FAILED ||
eventId == VCS_EVT_GESTURE)
return true;
return false;
}
public synchronized void FingerprintEventCallback(FingerprintEvent event) {
if (event == null) {
Log.e("Fingerprint", "FP - EventsCB()::Invalid event data!");
return;
}
if (isOperationComplete(event.eventId)) {
Log.i("Fingerprint", "Operation complete, setting to IDLE");
this.mOperation = IDLE;
}
if ((this.mOperation == GETPRINT) && ((event.eventId == VCS_EVT_EIV_FINGERPRINT_CAPTURED) ||
(event.eventId == VCS_EVT_SENSOR_FINGERPRINT_CAPTURE_FAILED))) {
this.mOperation = IDLE;
}
if (this.mEventListener != null) {
this.mEventListener.onEvent(event);
}
}
public int cancel() {
int ret = VCS_RESULT_FAILED;
if (mOperation == IDLE)
return ret;
ret = jniCancelOp();
mOperation = IDLE;
return ret;
}
public int cleanUp() {
int ret = VCS_RESULT_FAILED;
mEventListener = null;
ret = jniCleanupVcs();
return ret;
}
public int getEnrolledFingerList(String userId, VcsInt fingermask) {
if (null == userId)
userId = "";
int ret = jniGetEnrolledFingerList(userId, fingermask);;
return ret;
}
public int getFingerprintImage(){
int ret = VCS_RESULT_FAILED;
if (mOperation != IDLE)
return ret;
ret = jniGetFingerprintImage();
if (ret == VCS_RESULT_OK)
mOperation = GETPRINT;
return ret;
}
public int getFingerprintImage(ConsumerInfo info) {
int ret = VCS_RESULT_FAILED;
if (mOperation != IDLE)
return ret;
if (info == null)
Log.i("Fingerprint", "ConsumerInfo is null");
ret = jniGetFingerprintImageEx(info);
if (ret == VCS_RESULT_OK)
mOperation = GETPRINT;
return ret;
}
public int getUserList(VcsStringArray userList) {
VcsInt retCode = new VcsInt();
userList.strlist = jniGetUserList(retCode);
if (userList.strlist == null)
return retCode.num;
return VCS_RESULT_OK;
}
public String getVersion() {
if (mOperation != IDLE) {
Log.e("Fingerprint", "Other operation is in progress, cancelling request");
return null;
}
return jniGetVersion();
}
public int identify(String userId) {
int ret = VCS_RESULT_FAILED;
if (mOperation == IDENTIFY)
return VCS_RESULT_ALREADY_INPROGRESS;
if (mOperation != IDLE) {
return ret;
} else {
if (null == userId)
userId = "";
ret = jniIdentify(userId);
if (ret == VCS_RESULT_OK)
mOperation = IDENTIFY;
}
return ret;
}
public int protect(byte toProtect[], VcsAddInfo addInfo, VcsByteArray protectedData) {
if (toProtect == null || addInfo == null || protectedData == null)
return VCS_RESULT_INVALID_ARGUMENT;
return jniProtect(toProtect, addInfo, protectedData);
}
public int registerListener(EventListener listener) {
if (mOperation != IDLE)
return VCS_RESULT_FAILED;
mEventListener = listener;
return VCS_RESULT_OK;
}
public int setDetectFinger(int timeout) {
return jniSetDetectFinger(timeout);
}
public int setSecurityLevel(int level) {
if (mOperation != IDLE)
return VCS_RESULT_FAILED;
if (level == VCS_SECURITY_LEVEL_LOW || level == VCS_SECURITY_LEVEL_REGULAR ||
level == VCS_SECURITY_LEVEL_HIGH || level == VCS_SECURITY_LEVEL_VERY_HIGH)
return jniSetSecurityLevel(level);
return VCS_RESULT_INVALID_ARGUMENT;
}
public int unProtect(byte protectedData[], VcsAddInfo addInfo, VcsByteArray unProtectedData) {
if (protectedData == null || unProtectedData == null)
return VCS_RESULT_INVALID_ARGUMENT;
if (null == addInfo)
addInfo = new VcsAddInfo();
return jniUnprotect(protectedData, addInfo, unProtectedData);
}
}

View file

@ -1,24 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class FingerprintEvent {
public Object eventData;
public int eventId;
}

View file

@ -1,33 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class IdentifyResult {
public byte templateId[] = new byte[16];
public int matchedFingerIndexes[] = new int[20];
public int corrMinuCount[] = new int[4];
public int vMinuCount[] = new int[4];
public String appData;
public int fMinuCount;
public int fingerIndex;
public float matchRate;
public int matchScore;
public int templateUpdated;
public String userId;
}

View file

@ -1,24 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class RemoveEnroll {
public int fingerIndex;
public String userId;
}

View file

@ -1,25 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class SensorInfo {
public int flexId;
public String fwVersion;
public int productId;
}

View file

@ -1,56 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
import android.util.Log;
public class VLog {
private static final String TAG = "ValidityService";
private static final boolean DEBUG = false;
public static void i(final String message) {
Log.i(TAG, message);
}
public static void d(final String message) {
if (DEBUG) {
Log.d(TAG, message);
}
}
public static void v(final String message) {
if (DEBUG) {
Log.v(TAG, message);
}
}
public static void e(final String message, final Throwable t) {
Log.e(TAG, message, t);
}
public static void e(final String message) {
Log.e(TAG, message);
}
public static void w(final String message, final Throwable t) {
Log.w(TAG, message, t);
}
public static void w(final String message) {
Log.w(TAG, message);
}
}

View file

@ -1,390 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class ValidityService extends Service implements FingerprintCore.EventListener {
public static final String SOCKET_NAME = "validityservice";
public static final String SOCKET_NAME_CB = "validityservice_callback";
private LocalServerSocket mServerSocket = null;
private LocalServerSocket mServerSocketCB = null;
private LocalSocket mSocketCB = null;
public static final int CALL_BASE = 0;
public static final int CALL_INITSERVICE = CALL_BASE + 1;
public static final int CALL_ENROLL = CALL_BASE + 2; // userId ,fingerIndex
public static final int CALL_CANCEL = CALL_BASE + 3;
public static final int CALL_REMOVE = CALL_BASE + 4; // userId ,fingerIndex
public static final int CALL_IDENTIFY = CALL_BASE + 5; // userId
public static final int CALL_GET_ENROLLED_FINGER_LIST = CALL_BASE + 6; // userId
public static final int CALL_CLEANUP = CALL_BASE + 7;
public static final int CB_ERROR = 1;
public static final int CB_ENROLL = 2;
public static final int CB_REMOVED = 3;
public static final int CB_ACQUIRED = 4;
public static final int CB_AUTHENTICATED = 5;
private boolean mIsIdentify = false;
private int mLastEnrollFingerindex = 0;
private IdentifyResult mIdresult = null;
private boolean mEnrollBad = false;
private int mEnrollRepeatCount = 0;
private int mActiveGid = 0;
private boolean mIsNeedIdentify = false;
private int mIdentifyImage = 0;
Fingerprint fp = new Fingerprint(this, this);
/** We should set a password after we enroll one finger. This password is "123456q"
* The password hash method is SHA-1.
*/
public static final byte[] pwdhash = "bfff2dd4f1b310eb0dbf593bd83f94dd8d34077e".getBytes();
public int initService() {
int ret = fp.getSensorStatus();
VLog.i("init: ret=" + ret);
VLog.i("init: version=" + fp.getVersion());
notify_start();
if (ret != 0 && ret != 1004) return -1;
return 0;
}
public void notify_start() {
fp.cancel();
fp.notify(Fingerprint.VCS_NOTIFY_ENROLL_BEGIN, null);
}
public void notify_end() {
fp.cancel();
fp.notify(Fingerprint.VCS_NOTIFY_ENROLL_END, null);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
VLog.v("onCreate");
try {
mServerSocket = new LocalServerSocket(SOCKET_NAME);
mServerSocketCB = new LocalServerSocket(SOCKET_NAME_CB);
} catch (IOException e) {
VLog.v("in onCreate, making server socket: " + e);
return;
}
Thread t_server = new Thread() {
@Override
public void run() {
LocalSocket socket = null;
while (true) {
try {
VLog.v("Waiting for connection...");
socket = mServerSocket.accept();
VLog.v(".....Got socket: " + socket);
if (socket != null) {
startService(socket);
} else {
return;
}
} catch (IOException e) {
VLog.v("in accept: " + e);
}
}
}
};
Thread t_server_cb = new Thread() {
@Override
public void run() {
while (true) {
try {
VLog.v("Waiting for connection...");
mSocketCB = mServerSocketCB.accept();
VLog.v(".....Got socket: " + mSocketCB);
if (mSocketCB == null) {
return;
}
} catch (IOException e) {
VLog.v("in accept: " + e);
}
}
}
};
t_server.start();
t_server_cb.start();
ScreenReceiver receiver = new ScreenReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(receiver, filter);
}
private void startService(final LocalSocket socket) {
Thread t = new Thread() {
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
InputStreamReader isr = new InputStreamReader(is);
OutputStreamWriter osr = new OutputStreamWriter(os);
while (true) {
byte[] data = new byte[128];
int count = is.read(data);
int ret = -1;
String userId;
int fingerIndex;
for (int i = 0;i < count;i++){
VLog.d("data["+i+"]="+data[i]);
}
switch (data[0]) {
case CALL_INITSERVICE:
ret = initService();
break;
case CALL_ENROLL:
userId = "User_" + data[1];
fingerIndex = data[2];
mLastEnrollFingerindex = fingerIndex;
mEnrollBad = false;
mEnrollRepeatCount = 8;
fp.verifyPassword(userId, pwdhash);
ret = fp.enroll(userId, "", fingerIndex, Fingerprint.VCS_ENROLL_MODE_DEFAULT);
break;
case CALL_CANCEL:
ret = fp.cancel();
break;
case CALL_REMOVE:
userId = "User_" + data[1];
fingerIndex = data[2];
ret = fp.removeEnrolledFinger(userId, fingerIndex);
if (fingerIndex == VcsEvents.FINGER_INDEX_ALL) {
notify_end();
notify_start();
}
break;
case CALL_IDENTIFY:
userId = "User_" + data[1];
mIsIdentify = true;
fp.setSecurityLevel(VcsEvents.VCS_SECURITY_LEVEL_HIGH);
mIdresult = null;
mActiveGid = data[1];
ret = fp.identify(userId);
break;
case CALL_GET_ENROLLED_FINGER_LIST:
userId = "User_" + data[1];
VcsInt fingermask = new VcsInt();
fp.getEnrolledFingerList(userId, fingermask);
ret = fingermask.num;
break;
case CALL_CLEANUP:
notify_end();
ret = fp.cleanUp();
break;
default:
VLog.e("unknown function:" + data[0]);
}
String str = ret + "";
osr.write(str);
osr.flush();
}
} catch (IOException e) {
VLog.e("in startService loop: " + e.getMessage());
try {
socket.close();
} catch (IOException es) {
VLog.e("Cannot close socket: " + es.getMessage());
}
return;
}
}
};
t.start();
}
public int convertImageQuality(int imageQuality) {
switch (imageQuality) {
case VcsEvents.VCS_IMAGE_QUALITY_GOOD:
return 0; // FINGERPRINT_ACQUIRED_GOOD
case VcsEvents.VCS_IMAGE_QUALITY_REVERSE_MOTION:
case VcsEvents.VCS_IMAGE_QUALITY_TOO_SHORT:
case VcsEvents.VCS_IMAGE_QUALITY_WET_FINGER:
return 1; // FINGERPRINT_ACQUIRED_PARTIAL
case VcsEvents.VCS_IMAGE_QUALITY_STICTION:
case VcsEvents.VCS_IMAGE_QUALITY_SOMETHING_ON_THE_SENSOR:
return 3; // FINGERPRINT_ACQUIRED_IMAGER_DIRTY
case VcsEvents.VCS_IMAGE_QUALITY_TOO_SLOW:
return 4; // FINGERPRINT_ACQUIRED_TOO_SLOW
case VcsEvents.VCS_IMAGE_QUALITY_TOO_FAST:
return 5; // FINGERPRINT_ACQUIRED_TOO_FAST
default:
VLog.d("imageQuality="+imageQuality);
return 2; // FINGERPRINT_ACQUIRED_INSUFFICIENT
}
}
/** Get which finger we detected. */
public int getIdentifyFid() {
if (mIdresult == null) return 1;
return mIdresult.fingerIndex;
}
public void onEvent(final FingerprintEvent event) {
VLog.v("identify onEvent: receive event :" + event.eventId);
OutputStreamWriter osr = null;
try {
OutputStream os = mSocketCB.getOutputStream();
osr = new OutputStreamWriter(os);
String str = null;
switch (event.eventId) {
case VcsEvents.VCS_EVT_EIV_FINGERPRINT_CAPTURE_REDUNDANT:
str = CB_ACQUIRED + ":" + 1;
mEnrollBad = true;
break;
case VcsEvents.VCS_EVT_ENROLL_CAPTURE_STATUS:
EnrollCaptureStatus data_status = (EnrollCaptureStatus)event.eventData;
if (mEnrollBad) mEnrollBad = false;
else mEnrollRepeatCount = mEnrollRepeatCount - 1;
if (mEnrollRepeatCount != 0) {
str = CB_ENROLL + ":" + mLastEnrollFingerindex + ":" + mEnrollRepeatCount;
}
break;
case VcsEvents.VCS_EVT_EIV_FINGERPRINT_CAPTURED_BAD:
str = CB_ACQUIRED + ":" + convertImageQuality((int)event.eventData);
mEnrollBad = true;
break;
case VcsEvents.VCS_EVT_ENROLL_SUCCESS:
str = CB_ENROLL + ":" + mLastEnrollFingerindex + ":" + 0;
fp.setPassword("User_0", pwdhash);
break;
case VcsEvents.VCS_EVT_ENROLL_FAILED:
str = CB_ERROR + ":" + 2; //FINGERPRINT_ERROR_UNABLE_TO_PROCESS
VLog.e("enroll onEvent: enroll error, result=" + (int)event.eventData);
break;
case VcsEvents.VCS_EVT_VERIFY_COMPLETED:
case VcsEvents.VCS_EVT_IDENTIFY_COMPLETED:
mIdresult = (IdentifyResult)event.eventData;
break;
case VcsEvents.VCS_EVT_EIV_FINGERPRINT_CAPTURED:
FingerprintBitmap data_map = (FingerprintBitmap)event.eventData;
mIdentifyImage = convertImageQuality(data_map.quality);
break;
case VcsEvents.VCS_EVT_VERIFY_SUCCESS:
case VcsEvents.VCS_EVT_IDENTIFY_SUCCESS:
mIsIdentify = false;
str = CB_AUTHENTICATED + ":" + getIdentifyFid();
break;
case VcsEvents.VCS_EVT_SENSOR_REMOVED:
mIsIdentify = false;
str = CB_ERROR + ":" + 1; //FINGERPRINT_ERROR_HW_UNAVAILABLE
VLog.e("identify onEvent: identify error, result=" + (int)event.eventData);
break;
case VcsEvents.VCS_EVT_VERIFY_FAILED:
case VcsEvents.VCS_EVT_IDENTIFY_FAILED:
mIsIdentify = false;
VLog.e("identify onEvent: identify error, result=" + (int)event.eventData);
switch ((int)event.eventData) {
case VcsEvents.VCS_RESULT_BAD_QUALITY_IMAGE:
str = CB_ACQUIRED + ":" + mIdentifyImage;
case VcsEvents.VCS_RESULT_USER_DOESNT_EXIST:
fp.setSecurityLevel(VcsEvents.VCS_SECURITY_LEVEL_HIGH);
mIdresult = null;
mIsIdentify = true;
fp.identify("User_" + mActiveGid);
if (str == null) {
str = CB_ACQUIRED + ":" + 1; // FINGERPRINT_ACQUIRED_PARTIAL
}
break;
case VcsEvents.VCS_RESULT_OPERATION_CANCELED:
break;
default:
str = CB_ERROR + ":" + 2; //FINGERPRINT_ERROR_UNABLE_TO_PROCESS
}
break;
default:
VLog.v("identify onEvent: No need to process event :" + event.eventId);
}
if (str != null) {
osr.write(str);
osr.flush();
}
} catch (IOException e) {
VLog.e("in onEvent: " + e.getMessage());
try {
osr.close();
mSocketCB.close();
} catch (IOException es) {
VLog.e("Cannot close socket: " + es.getMessage());
}
return;
}
}
/** Our Keyguard will not call identify when turn on screen, so we need call it. */
public void onScreenOn() {
if (mIsNeedIdentify) {
mIsNeedIdentify = false;
fp.setSecurityLevel(VcsEvents.VCS_SECURITY_LEVEL_HIGH);
mIdresult = null;
mIsIdentify = true;
fp.identify("User_" + mActiveGid);
}
}
public void onScreenOff() {
if (mIsIdentify) {
mIsNeedIdentify = true;
}
}
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
onScreenOn();
}
else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
onScreenOff();
}
else VLog.e("Unknown intent:" + intent.getAction());
}
}
}

View file

@ -1,36 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ValidityServiceStarter extends Application {
@Override
public void onCreate() {
super.onCreate();
VLog.v("onCreate");
Intent serviceintent = new Intent(this, ValidityService.class);
startService(serviceintent);
}
}

View file

@ -1,31 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class VcsAddInfo {
public int algID;
public byte data[];
public VcsAddInfo() {
}
public VcsAddInfo(int algorithmID) {
algID = algorithmID;
}
}

View file

@ -1,23 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class VcsByteArray {
public byte data[];
}

View file

@ -1,179 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class VcsEvents {
public static final int FINGER_INDEX_LEFT_THUMB = 1;
public static final int FINGER_INDEX_LEFT_INDEX = 2;
public static final int FINGER_INDEX_LEFT_MIDDLE = 3;
public static final int FINGER_INDEX_LEFT_RING = 4;
public static final int FINGER_INDEX_LEFT_LITTLE = 5;
public static final int FINGER_INDEX_RIGHT_THUMB = 6;
public static final int FINGER_INDEX_RIGHT_INDEX = 7;
public static final int FINGER_INDEX_RIGHT_MIDDLE = 8;
public static final int FINGER_INDEX_RIGHT_RING = 9;
public static final int FINGER_INDEX_RIGHT_LITTLE = 10;
public static final int FINGER_INDEX_LEFT_THUMB_SECOND = 11;
public static final int FINGER_INDEX_LEFT_INDEX_SECOND = 12;
public static final int FINGER_INDEX_LEFT_MIDDLE_SECOND = 13;
public static final int FINGER_INDEX_LEFT_RING_SECOND = 14;
public static final int FINGER_INDEX_LEFT_LITTLE_SECOND = 15;
public static final int FINGER_INDEX_RIGHT_THUMB_SECOND = 16;
public static final int FINGER_INDEX_RIGHT_INDEX_SECOND = 17;
public static final int FINGER_INDEX_RIGHT_MIDDLE_SECOND = 18;
public static final int FINGER_INDEX_RIGHT_RING_SECOND = 19;
public static final int FINGER_INDEX_RIGHT_LITTLE_SECOND = 20;
public static final int FINGER_INDEX_ALL = 21;
public static final int VCS_EVT_SENSOR_REMOVED = 1;
public static final int VCS_EVT_SENSOR_DETECTED = 2;
public static final int VCS_EVT_SENSOR_READY_FOR_USE = 3;
public static final int VCS_EVT_SENSOR_FAILED_INITIALIZATION = 4;
public static final int VCS_EVT_SENSOR_FINGERPRINT_CAPTURE_COMPLETE = 5;
public static final int VCS_EVT_SENSOR_RAW_FINGERPRINT_CAPTURE_COMPLETE = 6;
public static final int VCS_EVT_SENSOR_FINGERPRINT_CAPTURE_FAILED = 7;
public static final int VCS_EVT_SENSOR_FINGERPRINT_CAPTURE_START = 8;
public static final int VCS_EVT_ALL_SENSORS_INITIALIZED = 9;
public static final int VCS_EVT_SENSOR_FINGERPRINT_FAILED_SWIPE_RETRY = 10;
public static final int VCS_EVT_FINGER_DETECTED = 11;
public static final int VCS_EVT_ENROLL_COMPLETED = 13;
public static final int VCS_EVT_VERIFY_COMPLETED = 14;
public static final int VCS_EVT_IDENTIFY_COMPLETED = 15;
public static final int VCS_EVT_ENROLL_NEXT_CAPTURE_START = 16;
public static final int VCS_EVT_EIV_FINGERPRINT_CAPTURED = 17;
public static final int VCS_EVT_FINGER_REMOVED = 20;
public static final int VCS_EVT_ENROLL_CAPTURE_STATUS = 32;
public static final int VCS_EVT_FINGER_SETTLED = 33;
public static final int VCS_EVT_SET_IR_FLAGS = 37;
public static final int VCS_EVT_SWIPE_DIRECTION = 41;
public static final int VCS_EVT_SWIPE_SPEED_UPDATE = 42;
public static final int VCS_EVT_EIV_FINGERPRINT_CAPTURED_BAD = 45;
public static final int VCS_EVT_SENSOR_NON_RECOVERABLE = 46;
public static final int VCS_EVT_ENVIRONMENT_NOISE_DETECTED = 47;
public static final int VCS_EVT_EIV_FINGERPRINT_CAPTURE_REDUNDANT = 49;
public static final int VCS_EVT_EIV_FINGERPRINT_CAPTURE_EARLY = 50;
public static final int VCS_EVT_ENROLL_SUCCESS = 421;
public static final int VCS_EVT_VERIFY_SUCCESS = 422;
public static final int VCS_EVT_IDENTIFY_SUCCESS = 423;
public static final int VCS_EVT_ENROLL_FAILED = 424;
public static final int VCS_EVT_VERIFY_FAILED = 425;
public static final int VCS_EVT_IDENTIFY_FAILED = 426;
public static final int VCS_EVT_GESTURE = 427;
public static final int VCS_EVT_SENSOR_INFO = 428;
public static final int VCS_IMAGE_QUALITY_GOOD = 0;
public static final int VCS_IMAGE_QUALITY_STICTION = 1;
public static final int VCS_IMAGE_QUALITY_TOO_FAST = 2;
public static final int VCS_IMAGE_QUALITY_TOO_SHORT = 4;
public static final int VCS_IMAGE_QUALITY_REVERSE_MOTION = 8;
public static final int VCS_IMAGE_QUALITY_TOO_SLOW = 16;
public static final int VCS_IMAGE_QUALITY_SOMETHING_ON_THE_SENSOR = 512;
public static final int VCS_IMAGE_QUALITY_ONE_HAND_SWIPE = 1024;
public static final int VCS_IMAGE_QUALITY_FINGER_OFFSET = 4096;
public static final int VCS_IMAGE_QUALITY_BAD_SWIPE = 8192;
public static final int VCS_IMAGE_QUALITY_SKEW_TOO_LARGE = 32768;
public static final int VCS_IMAGE_QUALITY_PRESSURE_TOO_LIGHT = 0x10000;
public static final int VCS_IMAGE_QUALITY_FINGER_OFFSET_TOO_FAR_LEFT = 0x20000;
public static final int VCS_IMAGE_QUALITY_FINGER_OFFSET_TOO_FAR_RIGHT = 0x40000;
public static final int VCS_IMAGE_QUALITY_PRESSURE_TOO_HARD = 0x80000;
public static final int VCS_IMAGE_QUALITY_ASP_DATA_INVALID = 0x100000;
public static final int VCS_IMAGE_QUALITY_NOT_A_FINGER_SWIPE = 0x200000;
public static final int VCS_IMAGE_QUALITY_BASELINE_DATA_INVALID = 0x400000;
public static final int VCS_IMAGE_QUALITY_WET_FINGER = 0x1000000;
public static final int VCS_IMAGE_QUALITY_FINGER_TOO_THIN = 0x2000000;
public static final int VCS_IMAGE_QUALITY_PARTIAL_TOUCH = 0x8000000;
public static final int VCS_IMAGE_QUALITY_EMPTY_TOUCH = 0x10000000;
public static final int VCS_IMAGE_QUALITY_GESTURE = 0x20000000;
public static final int VCS_IMAGE_QUALITY_PROCESS_FAILED = 0x40000000;
public static final int VCS_IMAGE_QUALITY_PROCESS_FAILED_FATAL = 0x80000000;
public static final int VCS_NOTIFY_AUTH_SESSION_BEGIN = 5;
public static final int VCS_NOTIFY_AUTH_SESSION_END = 6;
public static final int VCS_POLICY_AUTHENTICATE_ALWAYS = 1;
public static final int VCS_POLICY_AUTHENTICATE_ON_SCREEN_UNLOCK_TIMEOUT = 2;
public static final int VCS_POLICY_AUTHENTICATE_ON_PREVIOUS_IDENTIFY_TIMEOUT = 3;
public static final int VCS_PROTECT_ALG_SIMPLE_USER_DATA = 1;
public static final int VCS_PROTECT_ALG_SIMPLE_APP_DATA = 2;
public static final int VCS_RESULT_FAILED = -1;
public static final int VCS_RESULT_OK = 0;
public static final int VCS_RESULT_CANCEL = 1;
public static final int VCS_RESULT_OUT_OF_MEMORY = 2;
public static final int VCS_RESULT_NO_MORE_ENTRIES = 3;
public static final int VCS_RESULT_BAD_PARAM = 17;
public static final int VCS_RESULT_SENSOR_NOT_FOUND = 19;
public static final int VCS_RESULT_SENSOR_OPEN_FAILED = 22;
public static final int VCS_RESULT_TIMEOUT = 34;
public static final int VCS_RESULT_NULL_POINTER = 40;
public static final int VCS_RESULT_SENSOR_BUSY = 46;
public static final int VCS_RESULT_ERROR = 54;
public static final int VCS_RESULT_TEMPLATE_FILE_CREATION_FAILED = 64;
public static final int VCS_RESULT_USER_DOESNT_EXIST = 65;
public static final int VCS_RESULT_TEMPLATE_DOESNT_EXIST = 66;
public static final int VCS_RESULT_INVALID_USER_HANDLE = 70;
public static final int VCS_RESULT_TEMPLATE_CORRUPTED = 87;
public static final int VCS_RESULT_USER_FINGER_ALREADY_ENROLLED = 88;
public static final int VCS_RESULT_USER_DATA_CORRUPTED = 91;
public static final int VCS_RESULT_MATCHER_OPEN_FAILED = 300;
public static final int VCS_RESULT_MATCHER_CLOSE_FAILED = 301;
public static final int VCS_RESULT_MATCHER_MATCH_FAILED = 302;
public static final int VCS_RESULT_MATCHER_EXTRACT_FAILED = 303;
public static final int VCS_RESULT_MATCHER_ENROLL_FAILED = 304;
public static final int VCS_RESULT_MATCHER_VERIFY_FAILED = 305;
public static final int VCS_RESULT_MATCHER_ADD_IMAGE_FAILED = 306;
public static final int VCS_RESULT_MATCHER_MATCH_IMAGE_FAILED = 307;
public static final int VCS_RESULT_MATCHER_CHECK_QUALITY_FAILED = 308;
public static final int VCS_RESULT_SERVICE_NOT_RUNNING = 321;
public static final int VCS_RESULT_SENSOR_NOT_READY_FOR_USE = 358;
public static final int VCS_RESULT_SENSOR_IS_REMOVED = 360;
public static final int VCS_RESULT_OPERATION_CANCELED = 361;
public static final int VCS_RESULT_USER_IDENTIFICATION_FAILED = 362;
public static final int VCS_RESULT_USER_VERIFICATION_FAILED = 363;
public static final int VCS_RESULT_MATCH_FAILED = 367;
public static final int VCS_RESULT_SERVICE_STOPPED = 500;
public static final int VCS_RESULT_GET_PRINT_STOPPED = 501;
public static final int VCS_RESULT_OPERATION_DENIED = 510;
public static final int VCS_RESULT_PIPE_ERROR = 511;
public static final int VCS_RESULT_SENSOR_KEYS_NOT_READY = 512;
public static final int VCS_RESULT_BAD_DEVICE = 513;
public static final int VCS_RESULT_TOO_MANY_BAD_SWIPES = 515;
public static final int VCS_RESULT_BAD_QUALITY_IMAGE = 601;
public static final int VCS_RESULT_KEYDATA_NOT_FOUND = 777;
public static final int VCS_RESULT_DATA_STORE_FAILED = 1001;
public static final int VCS_RESULT_DATA_RETRIEVE_FAILED = 1002;
public static final int VCS_RESULT_DATA_REMOVE_FAILED = 1003;
public static final int VCS_RESULT_ALREADY_INPROGRESS = 1004;
public static final int VCS_RESULT_NOT_IMPLEMENTED = 1005;
public static final int VCS_RESULT_INVALID_ARGUMENT = 1006;
public static final int VCS_SECURITY_LEVEL_LOW = 0;
public static final int VCS_SECURITY_LEVEL_REGULAR = 1;
public static final int VCS_SECURITY_LEVEL_HIGH = 2;
public static final int VCS_SECURITY_LEVEL_VERY_HIGH = 3;
public static final int VCS_SWIPE_DIRECTION_UP = 0;
public static final int VCS_SWIPE_DIRECTION_DOWN = 1;
public static final int VCS_SWIPE_DIRECTION_LEFT = 3;
public static final int VCS_SWIPE_DIRECTION_RIGHT = 4;
public static final int VCS_SWIPE_DIRECTION_REST = 5;
}

View file

@ -1,23 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class VcsInt {
public int num;
}

View file

@ -1,23 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 The Mokee Project
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.validity.fingerprint;
public class VcsStringArray {
public String strlist[];
}