First pass at adding FingerprintManagerService

This adds a new service for monitoring and enrolling fingerprints
to the platform.

Fixed documentation links.

Change-Id: I66013be5e09be9c5f9746c46aacf32d3e26c3b73
This commit is contained in:
Jim Miller
2014-04-29 18:18:47 -07:00
parent 6c8e788e37
commit 08fa40c5cb
13 changed files with 762 additions and 0 deletions

View File

@@ -199,6 +199,8 @@ LOCAL_SRC_FILES += \
core/java/android/service/dreams/IDozeHardware.aidl \
core/java/android/service/dreams/IDreamManager.aidl \
core/java/android/service/dreams/IDreamService.aidl \
core/java/android/service/fingerprint/IFingerprintService.aidl \
core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl \
core/java/android/service/trust/ITrustAgentService.aidl \
core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
core/java/android/service/voice/IVoiceInteractionService.aidl \

View File

@@ -6614,6 +6614,7 @@ package android.content {
field public static final java.lang.String DISPLAY_SERVICE = "display";
field public static final java.lang.String DOWNLOAD_SERVICE = "download";
field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
field public static final java.lang.String HDMI_CEC_SERVICE = "hdmi_cec";
field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
field public static final java.lang.String INPUT_SERVICE = "input";
@@ -25059,6 +25060,36 @@ package android.service.dreams {
}
package android.service.fingerprint {
public class FingerprintManager {
ctor public FingerprintManager(android.content.Context);
method public void enroll(long);
method public void remove(int);
method public void startListening(android.service.fingerprint.FingerprintManagerReceiver);
method public void stopListening();
field protected static final boolean DEBUG = true;
field public static final int FINGERPRINT_ERROR = -1; // 0xffffffff
field public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2; // 0x2
field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
field public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10; // 0xfffffff6
field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
field public static final int FINGERPRINT_SCANNED = 1; // 0x1
field public static final int FINGERPRINT_TEMPLATE_ENROLLING = 2; // 0x2
field public static final int FINGERPRINT_TEMPLATE_REMOVED = 4; // 0x4
}
public class FingerprintManagerReceiver {
ctor public FingerprintManagerReceiver();
method public void onEnrollResult(int, int);
method public void onError(int);
method public void onRemoved(int);
method public void onScanned(int, int);
}
}
package android.service.notification {
public abstract class NotificationListenerService extends android.app.Service {

View File

@@ -106,6 +106,9 @@ import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
import android.service.fingerprint.FingerprintManager;
import android.service.fingerprint.FingerprintManagerReceiver;
import android.service.fingerprint.FingerprintService;
import android.telephony.TelephonyManager;
import android.tv.ITvInputManager;
import android.tv.TvInputManager;
@@ -451,6 +454,11 @@ class ContextImpl extends Context {
return new KeyguardManager();
}});
registerService(FINGERPRINT_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new FingerprintManager(ctx);
}});
registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());

View File

@@ -2375,6 +2375,16 @@ public abstract class Context {
*/
public static final String AUDIO_SERVICE = "audio";
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.service.fingerprint.FingerprintManager} for handling management
* of fingerprints.
*
* @see #getSystemService
* @see android.app.FingerprintManager
*/
public static final String FINGERPRINT_SERVICE = "fingerprint";
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.media.MediaRouter} for controlling and managing

View File

@@ -3479,6 +3479,12 @@ public final class Settings {
public static final String LOCK_SCREEN_APPWIDGET_IDS =
"lock_screen_appwidget_ids";
/**
* List of enrolled fingerprint identifiers (comma-delimited).
* @hide
*/
public static final String USER_FINGERPRINT_IDS = "user_fingerprint_ids";
/**
* Id of the appwidget shown on the lock screen when appwidgets are disabled.
* @hide

View File

@@ -0,0 +1,200 @@
/**
* Copyright (C) 2014 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 android.service.fingerprint;
import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
/**
* A class that coordinates access to the fingerprint hardware.
*/
public class FingerprintManager {
private static final String TAG = "FingerprintManager";
protected static final boolean DEBUG = true;
private static final String FINGERPRINT_SERVICE_PACKAGE = "com.android.service.fingerprint";
private static final String FINGERPRINT_SERVICE_CLASS =
"com.android.service.fingerprint.FingerprintService";
private static final int MSG_ENROLL_RESULT = 100;
private static final int MSG_SCANNED = 101;
private static final int MSG_ERROR = 102;
private static final int MSG_REMOVED = 103;
public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10;
public static final int FINGERPRINT_ERROR = -1; // One of the error messages below.
// Progress messages.
public static final int FINGERPRINT_SCANNED = 1;
public static final int FINGERPRINT_TEMPLATE_ENROLLING = 2;
public static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
// Error messages. Must agree with fingerprint HAL definitions.
public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2;
public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
private IFingerprintService mService;
private FingerprintManagerReceiver mClientReceiver;
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (mClientReceiver != null) {
switch(msg.what) {
case MSG_ENROLL_RESULT:
mClientReceiver.onEnrollResult(msg.arg1, msg.arg2);
break;
case MSG_SCANNED:
mClientReceiver.onScanned(msg.arg1, msg.arg2);
break;
case MSG_ERROR:
mClientReceiver.onError(msg.arg1);
break;
case MSG_REMOVED:
mClientReceiver.onRemoved(msg.arg1);
}
}
}
};
public FingerprintManager(Context context) {
// Connect to service...
Intent intent = new Intent();
intent.setClassName(FINGERPRINT_SERVICE_PACKAGE, FINGERPRINT_SERVICE_CLASS);
if (!context.bindServiceAsUser(intent, mFingerprintConnection,
Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF)) {
if (DEBUG) Log.v(TAG, "Can't bind to " + FINGERPRINT_SERVICE_CLASS);
}
}
private final ServiceConnection mFingerprintConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "Connected to FingerprintService");
mService = IFingerprintService.Stub.asInterface(service);
try {
mService.startListening(mServiceReceiver, getCurrentUserId());
} catch (RemoteException e) {
if (DEBUG) Log.v(TAG, "Failed to set callback", e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "Disconnected from FingerprintService");
mService = null;
}
};
private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
public void onEnrollResult(int fingerprintId, int remaining) {
mHandler.obtainMessage(MSG_ENROLL_RESULT, fingerprintId, remaining).sendToTarget();
}
public void onScanned(int fingerprintId, int confidence) {
mHandler.obtainMessage(MSG_SCANNED, fingerprintId, confidence)
.sendToTarget();;
}
public void onError(int error) {
mHandler.obtainMessage(MSG_ERROR, error, 0).sendToTarget();
}
public void onRemoved(int fingerprintId) {
mHandler.obtainMessage(MSG_REMOVED, fingerprintId, 0).sendToTarget();
}
};
/**
* Start the enrollment process. Timeout dictates how long to wait for the user to
* enroll a fingerprint.
*
* @param timeout
*/
public void enroll(long timeout) {
if (mServiceReceiver == null) {
throw new IllegalStateException("enroll: Call registerCallback() first");
}
if (mService != null) try {
mService.enroll(timeout, getCurrentUserId());
} catch (RemoteException e) {
Log.v(TAG, "Remote exception while enrolling: ", e);
}
}
/**
* Remove the given fingerprintId from the system. FingerprintId of 0 has special meaning
* which is to delete all fingerprint data for the current user. Use with caution.
* @param fingerprintId
*/
public void remove(int fingerprintId) {
if (mService != null) try {
mService.remove(fingerprintId, getCurrentUserId());
} catch (RemoteException e) {
Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e);
}
}
/**
* Starts listening for fingerprint events. When a finger is scanned or recognized, the
* client will be notified via the callback.
*/
public void startListening(FingerprintManagerReceiver receiver) {
mClientReceiver = receiver;
if (mService != null) {
try {
mService.startListening(mServiceReceiver, getCurrentUserId());
} catch (RemoteException e) {
Log.v(TAG, "Remote exception in startListening(): ", e);
}
}
}
private int getCurrentUserId() {
try {
return ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
Log.w(TAG, "Failed to get current user id\n");
return UserHandle.USER_NULL;
}
}
/**
* Stops the client from listening to fingerprint events.
*/
public void stopListening() {
mClientReceiver = null;
if (mService != null) {
try {
mService.stopListening(getCurrentUserId());
} catch (RemoteException e) {
Log.v(TAG, "Remote exception in stopListening(): ", e);
}
} else {
Log.w(TAG, "stopListening(): Service not connected!");
}
}
}

View File

@@ -0,0 +1,59 @@
package android.service.fingerprint;
/**
* Copyright (C) 2014 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.
*/
public class FingerprintManagerReceiver {
/**
* Fingerprint enrollment progress update. Enrollment is considered complete if
* remaining hits 0 without {@link #onError(int)} being called.
*
* @param fingerprintId the fingerprint we're currently enrolling
* @param remaining the number of samples required to complete enrollment. It's up to
* the hardware to define what each step in enrollment means. Some hardware
* requires multiple samples of the same part of the finger. Others require sampling of
* different parts of the finger. The enrollment flow can use remaining to
* mean "step x" of the process or "just need another sample."
*/
public void onEnrollResult(int fingerprintId, int remaining) { }
/**
* Fingerprint scan detected. Most clients will use this function to detect a fingerprint
*
* @param fingerprintId is the finger the hardware has detected.
* @param confidence from 0 (no confidence) to 65535 (high confidence). Fingerprint 0 has
* special meaning - the finger wasn't recognized.
*/
public void onScanned(int fingerprintId, int confidence) { }
/**
* An error was detected during scan or enrollment. One of
* {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE},
* {@link FingerprintManager#FINGERPRINT_ERROR_BAD_CAPTURE} or
* {@link FingerprintManager#FINGERPRINT_ERROR_TIMEOUT}
* {@link FingerprintManager#FINGERPRINT_ERROR_NO_SPACE}
*
* @param error one of the above error codes
*/
public void onError(int error) { }
/**
* The given fingerprint template was successfully removed by the driver.
* See {@link FingerprintManager#remove(int)}
*
* @param fingerprintId id of template to remove.
*/
public void onRemoved(int fingerprintId) { }
}

View File

@@ -0,0 +1,219 @@
/**
* Copyright (C) 2014 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 android.service.fingerprint;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Slog;
import java.io.PrintWriter;
import java.util.HashMap;
/**
* A service to manage multiple clients that want to access the fingerprint HAL API.
* The service is responsible for maintaining a list of clients and dispatching all
* fingerprint -related events.
*
* @hide
*/
public class FingerprintService extends Service {
private final String TAG = FingerprintService.class.getSimpleName() +
"[" + getClass().getSimpleName() + "]";
private static final boolean DEBUG = true;
HashMap<IFingerprintServiceReceiver, ClientData> mClients =
new HashMap<IFingerprintServiceReceiver, ClientData>();
private static final int MSG_NOTIFY = 10;
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_NOTIFY:
handleNotify(msg.arg1, msg.arg2, (Integer) msg.obj);
break;
default:
Slog.w(TAG, "Unknown message:" + msg.what);
}
}
};
private static final int STATE_IDLE = 0;
private static final int STATE_LISTENING = 1;
private static final int STATE_ENROLLING = 2;
private static final int STATE_DELETING = 3;
private static final long MS_PER_SEC = 1000;
private static final class ClientData {
public IFingerprintServiceReceiver receiver;
int state;
int userId;
}
@Override
public final IBinder onBind(Intent intent) {
if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
return new FingerprintServiceWrapper();
}
// JNI methods to communicate from FingerprintManagerService to HAL
native int nativeEnroll(int timeout);
native int nativeRemove(int fingerprintId);
// JNI methods for communicating from HAL to clients
void notify(int msg, int arg1, int arg2) {
mHandler.obtainMessage(MSG_NOTIFY, msg, arg1, arg2).sendToTarget();
}
void handleNotify(int msg, int arg1, int arg2) {
for (int i = 0; i < mClients.size(); i++) {
ClientData clientData = mClients.get(i);
switch (msg) {
case FingerprintManager.FINGERPRINT_ERROR: {
if (clientData.state != STATE_IDLE) {
// FINGERPRINT_ERROR_HW_UNAVAILABLE
// FINGERPRINT_ERROR_BAD_CAPTURE
// FINGERPRINT_ERROR_TIMEOUT
// FINGERPRINT_ERROR_NO_SPACE
final int error = arg1;
clientData.state = STATE_IDLE;
if (clientData.receiver != null) {
try {
clientData.receiver.onError(error);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
}
}
}
}
break;
case FingerprintManager.FINGERPRINT_SCANNED: {
final int fingerId = arg1;
final int confidence = arg2;
if (clientData.state == STATE_LISTENING && clientData.receiver != null) {
try {
clientData.receiver.onScanned(fingerId, confidence);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
}
}
break;
}
case FingerprintManager.FINGERPRINT_TEMPLATE_ENROLLING: {
if (clientData.state == STATE_ENROLLING) {
final int fingerId = arg1;
final int remaining = arg2;
if (remaining == 0) {
FingerprintUtils.addFingerprintIdForUser(fingerId,
getContentResolver(), clientData.userId);
clientData.state = STATE_IDLE; // Nothing left to do
}
if (clientData.receiver != null) {
try {
clientData.receiver.onEnrollResult(fingerId, remaining);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
}
}
}
break;
}
case FingerprintManager.FINGERPRINT_TEMPLATE_REMOVED: {
int fingerId = arg1;
if (fingerId == 0) throw new IllegalStateException("Got illegal id from HAL");
if (clientData.state == STATE_DELETING) {
FingerprintUtils.removeFingerprintIdForUser(fingerId, getContentResolver(),
clientData.userId);
if (clientData.receiver != null) {
try {
clientData.receiver.onRemoved(fingerId);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
}
}
}
}
break;
}
}
}
int enroll(IFingerprintServiceReceiver receiver, long timeout, int userId) {
ClientData clientData = mClients.get(receiver);
if (clientData != null) {
if (clientData.userId != userId) throw new IllegalStateException("Bad user");
clientData.state = STATE_ENROLLING;
return nativeEnroll((int) (timeout / MS_PER_SEC));
}
return -1;
}
int remove(IFingerprintServiceReceiver receiver, int fingerId, int userId) {
ClientData clientData = mClients.get(receiver);
if (clientData != null) {
if (clientData.userId != userId) throw new IllegalStateException("Bad user");
clientData.state = STATE_DELETING;
// The fingerprint id will be removed when we get confirmation from the HAL
return nativeRemove(fingerId);
}
return -1;
}
void startListening(IFingerprintServiceReceiver receiver, int userId) {
ClientData clientData = new ClientData();
clientData.state = STATE_LISTENING;
clientData.receiver = receiver;
clientData.userId = userId;
mClients.put(receiver, clientData);
}
void stopListening(IFingerprintServiceReceiver receiver, int userId) {
ClientData clientData = mClients.get(receiver);
if (clientData != null) {
clientData.state = STATE_IDLE;
clientData.userId = -1;
clientData.receiver = null;
}
mClients.remove(receiver);
}
private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
IFingerprintServiceReceiver mReceiver;
public int enroll(long timeout, int userId) {
return mReceiver != null ? FingerprintService.this.enroll(mReceiver, timeout, userId)
: FingerprintManager.FINGERPRINT_ERROR_NO_RECEIVER;
}
public int remove(int fingerprintId, int userId) {
return FingerprintService.this.remove(mReceiver, fingerprintId, userId);
}
public void startListening(IFingerprintServiceReceiver receiver, int userId) {
mReceiver = receiver;
FingerprintService.this.startListening(receiver, userId);
}
public void stopListening(int userId) {
FingerprintService.this.stopListening(mReceiver, userId);
}
}
}

View File

@@ -0,0 +1,85 @@
/**
* Copyright (C) 2014 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 android.service.fingerprint;
import android.content.ContentResolver;
import android.provider.Settings;
import android.util.Log;
import java.util.Arrays;
class FingerprintUtils {
private static final boolean DEBUG = true;
private static final String TAG = "FingerprintUtils";
public static int[] getFingerprintIdsForUser(ContentResolver res, int userId) {
String fingerIdsRaw = Settings.Secure.getStringForUser(res,
Settings.Secure.USER_FINGERPRINT_IDS, userId);
String[] fingerStringIds = fingerIdsRaw.replace("[","").replace("]","").split(", ");
int result[] = new int[fingerStringIds.length];
for (int i = 0; i < result.length; i++) {
try {
result[i] = Integer.decode(fingerStringIds[i]);
} catch (NumberFormatException e) {
if (DEBUG) Log.d(TAG, "Error when parsing finger id " + fingerStringIds[i]);
}
}
return result;
}
public static void addFingerprintIdForUser(int fingerId, ContentResolver res, int userId) {
int[] fingerIds = getFingerprintIdsForUser(res, userId);
// FingerId 0 has special meaning.
if (fingerId == 0) return;
// Don't allow dups
for (int i = 0; i < fingerIds.length; i++) {
if (fingerIds[i] == fingerId) return;
}
int[] newList = Arrays.copyOf(fingerIds, fingerIds.length + 1);
newList[fingerIds.length] = fingerId;
Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
Arrays.toString(newList), userId);
}
public static boolean removeFingerprintIdForUser(int fingerId, ContentResolver res, int userId)
{
// FingerId 0 has special meaning. The HAL layer is supposed to remove each finger one
// at a time and invoke notify() for each fingerId. If we get called with 0 here, it means
// something bad has happened.
if (fingerId == 0) throw new IllegalStateException("Bad fingerId");
int[] fingerIds = getFingerprintIdsForUser(res, userId);
int[] resultIds = Arrays.copyOf(fingerIds, fingerIds.length);
int resultCount = 0;
for (int i = 0; i < fingerIds.length; i++) {
if (fingerId != fingerIds[i]) {
resultIds[resultCount++] = fingerIds[i];
}
}
if (resultCount > 0) {
Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
Arrays.toString(Arrays.copyOf(resultIds, resultCount)), userId);
return true;
}
return false;
}
};

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2014 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 android.service.fingerprint;
import android.os.Bundle;
import android.service.fingerprint.IFingerprintServiceReceiver;
/**
* Communication channel from client to the fingerprint service.
* @hide
*/
interface IFingerprintService {
// Returns 0 if successfully started, -1 otherwise
int enroll(long timeout, int userId);
// Returns 0 if fingerprintId's template can be removed, -1 otherwise
int remove(int fingerprintId, int userId);
// Start listening for fingerprint events. This has the side effect of starting
// the hardware if not already started.
oneway void startListening(IFingerprintServiceReceiver receiver, int userId);
// Stops listening for fingerprints
oneway void stopListening(int userId);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2014 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 android.service.fingerprint;
import android.os.Bundle;
import android.os.UserHandle;
/**
* Communication channel from the FingerprintService back to FingerprintManager.
* @hide
*/
oneway interface IFingerprintServiceReceiver {
void onEnrollResult(int fingerprintId, int remaining);
void onScanned(int fingerprintId, int confidence);
void onError(int error);
void onRemoved(int fingerprintId);
}

View File

@@ -141,6 +141,7 @@ LOCAL_SRC_FILES:= \
android_util_FileObserver.cpp \
android/opengl/poly_clip.cpp.arm \
android/opengl/util.cpp.arm \
android_server_FingerprintManager.cpp \
android_server_NetworkManagementSocketTagger.cpp \
android_server_Watchdog.cpp \
android_ddm_DdmHandleNativeHeap.cpp \

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2014 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.
*/
#define LOG_TAG "Fingerprint-JNI"
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include <utils/Log.h>
namespace android {
static struct {
jclass clazz;
jmethodID notify;
} gFingerprintManagerClassInfo;
static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) {
return -1; // TODO
}
static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) {
return -1; // TODO
}
// ----------------------------------------------------------------------------
static const JNINativeMethod g_methods[] = {
{ "nativeEnroll", "(I)I", (void*)nativeEnroll },
{ "nativeRemove", "(I)I", (void*)nativeRemove },
};
#define FIND_CLASS(var, className) \
var = env->FindClass(className); \
LOG_FATAL_IF(! var, "Unable to find class " className); \
var = jclass(env->NewGlobalRef(var));
#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
LOG_FATAL_IF(! var, "Unable to find static method" methodName);
#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
LOG_FATAL_IF(! var, "Unable to find method" methodName);
#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
LOG_FATAL_IF(! var, "Unable to find field " fieldName);
int register_android_server_FingerprintManager(JNIEnv* env) {
FIND_CLASS(gFingerprintManagerClassInfo.clazz,
"android/service/fingerprint/FingerprintManager");
GET_METHOD_ID(gFingerprintManagerClassInfo.notify, gFingerprintManagerClassInfo.clazz,
"notify", "(III)V");
return AndroidRuntime::registerNativeMethods(
env, "com/android/service/fingerprint/FingerprintManager", g_methods, NELEM(g_methods));
}
} // namespace android