diff options
12 files changed, 683 insertions, 331 deletions
diff --git a/api/current.txt b/api/current.txt index 3e5a695db49f..760d68b877cc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26011,29 +26011,61 @@ package android.service.dreams { package android.service.fingerprint { public class FingerprintManager { - ctor public FingerprintManager(android.content.Context); + ctor public FingerprintManager(android.content.Context, android.service.fingerprint.IFingerprintService); method public void enroll(long); + method public void enrollCancel(); method public boolean enrolledAndEnabled(); method public void remove(int); method public void startListening(android.service.fingerprint.FingerprintManagerReceiver); method public void stopListening(); + field public static final int FINGERPRINT_ACQUIRED = 1; // 0x1 + field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0 + field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 4; // 0x4 + field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2 + field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1 + field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 16; // 0x10 + field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 8; // 0x8 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_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 + field public static final int FINGERPRINT_PROCESSED = 2; // 0x2 + field public static final int FINGERPRINT_TEMPLATE_ENROLLING = 3; // 0x3 field public static final int FINGERPRINT_TEMPLATE_REMOVED = 4; // 0x4 } public class FingerprintManagerReceiver { ctor public FingerprintManagerReceiver(); + method public void onAcquired(int); method public void onEnrollResult(int, int); method public void onError(int); + method public void onProcessed(int); method public void onRemoved(int); - method public void onScanned(int, int); + } + + public class FingerprintUtils { + ctor public FingerprintUtils(); + method public static void addFingerprintIdForUser(int, android.content.ContentResolver, int); + method public static int[] getFingerprintIdsForUser(android.content.ContentResolver, int); + method public static boolean removeFingerprintIdForUser(int, android.content.ContentResolver, int); + } + + public abstract interface IFingerprintService implements android.os.IInterface { + method public abstract void enroll(android.os.IBinder, long, int) throws android.os.RemoteException; + method public abstract void enrollCancel(android.os.IBinder, int) throws android.os.RemoteException; + method public abstract void remove(android.os.IBinder, int, int) throws android.os.RemoteException; + method public abstract void startListening(android.os.IBinder, android.service.fingerprint.IFingerprintServiceReceiver, int) throws android.os.RemoteException; + method public abstract void stopListening(android.os.IBinder, int) throws android.os.RemoteException; + } + + public abstract interface IFingerprintServiceReceiver implements android.os.IInterface { + method public abstract void onAcquired(int) throws android.os.RemoteException; + method public abstract void onEnrollResult(int, int) throws android.os.RemoteException; + method public abstract void onError(int) throws android.os.RemoteException; + method public abstract void onProcessed(int) throws android.os.RemoteException; + method public abstract void onRemoved(int) throws android.os.RemoteException; } } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index ab3bb4966624..a42bd3b92730 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -115,9 +115,8 @@ import android.os.storage.IMountService; import android.os.storage.StorageManager; import android.print.IPrintManager; import android.print.PrintManager; +import android.service.fingerprint.IFingerprintService; import android.service.fingerprint.FingerprintManager; -import android.service.fingerprint.FingerprintManagerReceiver; -import android.service.fingerprint.FingerprintService; import android.telecomm.TelecommManager; import android.telephony.TelephonyManager; import android.content.ClipboardManager; @@ -466,11 +465,6 @@ 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()); @@ -690,6 +684,7 @@ class ContextImpl extends Context { return new MediaSessionManager(ctx); } }); + registerService(TRUST_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(TRUST_SERVICE); @@ -697,6 +692,14 @@ class ContextImpl extends Context { } }); + registerService(FINGERPRINT_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(FINGERPRINT_SERVICE); + IFingerprintService service = IFingerprintService.Stub.asInterface(b); + return new FingerprintManager(ctx.getOuterContext(), service); + } + }); + registerService(TV_INPUT_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder iBinder = ServiceManager.getService(TV_INPUT_SERVICE); diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java index 2fcec52d2e65..b6137d11b2cc 100644 --- a/core/java/android/service/fingerprint/FingerprintManager.java +++ b/core/java/android/service/fingerprint/FingerprintManager.java @@ -22,12 +22,14 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; +import android.util.Slog; /** * A class that coordinates access to the fingerprint hardware. @@ -36,31 +38,40 @@ import android.util.Log; public class FingerprintManager { private static final String TAG = "FingerprintManager"; private 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; + private static final int MSG_ACQUIRED = 101; + private static final int MSG_PROCESSED = 102; + private static final int MSG_ERROR = 103; + private static final int MSG_REMOVED = 104; + // Errors generated by layers above HAL 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; + // Message types. Must agree with HAL (fingerprint.h) + public static final int FINGERPRINT_ERROR = -1; + public static final int FINGERPRINT_ACQUIRED = 1; + public static final int FINGERPRINT_PROCESSED = 2; + public static final int FINGERPRINT_TEMPLATE_ENROLLING = 3; public static final int FINGERPRINT_TEMPLATE_REMOVED = 4; - // Error messages. Must agree with fingerprint HAL definitions. + // Error messages. Must agree with HAL (fingerprint.h) public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; - public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2; + public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; public static final int FINGERPRINT_ERROR_TIMEOUT = 3; public static final int FINGERPRINT_ERROR_NO_SPACE = 4; + // FINGERPRINT_ACQUIRED messages. Must agree with HAL (fingerprint.h) + public static final int FINGERPRINT_ACQUIRED_GOOD = 0; + public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; + public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; + public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 4; + public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 8; + public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 16; + private IFingerprintService mService; private FingerprintManagerReceiver mClientReceiver; private Context mContext; + private IBinder mToken = new Binder(); private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { @@ -69,8 +80,11 @@ public class FingerprintManager { case MSG_ENROLL_RESULT: mClientReceiver.onEnrollResult(msg.arg1, msg.arg2); break; - case MSG_SCANNED: - mClientReceiver.onScanned(msg.arg1, msg.arg2); + case MSG_ACQUIRED: + mClientReceiver.onAcquired(msg.arg1); + break; + case MSG_PROCESSED: + mClientReceiver.onProcessed(msg.arg1); break; case MSG_ERROR: mClientReceiver.onError(msg.arg1); @@ -82,45 +96,26 @@ public class FingerprintManager { } }; - public FingerprintManager(Context context) { + public FingerprintManager(Context context, IFingerprintService service) { mContext = 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); + mService = service; + if (mService == null) { + Slog.v(TAG, "FingerprintManagerService was null"); } } - 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 onAcquired(int acquireInfo) { + mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0).sendToTarget(); + } + + public void onProcessed(int fingerprintId) { + mHandler.obtainMessage(MSG_PROCESSED, fingerprintId, 0).sendToTarget(); } public void onError(int error) { @@ -151,12 +146,14 @@ public class FingerprintManager { */ public void enroll(long timeout) { if (mServiceReceiver == null) { - throw new IllegalStateException("enroll: Call registerCallback() first"); + sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0); + return; } if (mService != null) try { - mService.enroll(timeout, getCurrentUserId()); + mService.enroll(mToken, timeout, getCurrentUserId()); } catch (RemoteException e) { Log.v(TAG, "Remote exception while enrolling: ", e); + sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); } } @@ -166,10 +163,19 @@ public class FingerprintManager { * @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); + if (mServiceReceiver == null) { + sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0); + return; + } + if (mService != null) { + try { + mService.remove(mToken, fingerprintId, getCurrentUserId()); + } catch (RemoteException e) { + Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e); + } + } else { + Log.w(TAG, "remove(): Service not connected!"); + sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); } } @@ -181,10 +187,13 @@ public class FingerprintManager { mClientReceiver = receiver; if (mService != null) { try { - mService.startListening(mServiceReceiver, getCurrentUserId()); + mService.startListening(mToken, mServiceReceiver, getCurrentUserId()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in startListening(): ", e); } + } else { + Log.w(TAG, "startListening(): Service not connected!"); + sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); } } @@ -201,15 +210,38 @@ public class FingerprintManager { * Stops the client from listening to fingerprint events. */ public void stopListening() { - mClientReceiver = null; if (mService != null) { try { - mService.stopListening(getCurrentUserId()); + mService.stopListening(mToken, getCurrentUserId()); + mClientReceiver = null; } catch (RemoteException e) { Log.v(TAG, "Remote exception in stopListening(): ", e); } } else { Log.w(TAG, "stopListening(): Service not connected!"); + sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); + } + } + + public void enrollCancel() { + if (mServiceReceiver == null) { + sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0); + return; } + if (mService != null) { + try { + mService.enrollCancel(mToken, getCurrentUserId()); + mClientReceiver = null; + } catch (RemoteException e) { + Log.v(TAG, "Remote exception in enrollCancel(): ", e); + sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); + } + } else { + Log.w(TAG, "enrollCancel(): Service not connected!"); + } + } + + private void sendError(int msg, int arg1, int arg2) { + mHandler.obtainMessage(msg, arg1, arg2); } }
\ No newline at end of file diff --git a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java index 34f16558acca..e5193f572b80 100644 --- a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java +++ b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java @@ -30,18 +30,32 @@ public class FingerprintManagerReceiver { public void onEnrollResult(int fingerprintId, int remaining) { } /** - * Fingerprint scan detected. Most clients will use this function to detect a fingerprint + * Fingerprint touch detected, but not processed yet. Clients will use this message to + * determine a good or bad scan before the fingerprint is processed. This is meant for the + * client to provide feedback about the scan or alert the user that recognition is to follow. * - * @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. + * @param acquiredInfo one of: + * {@link FingerprintManager#FINGERPRINT_ACQUIRED_GOOD}, + * {@link FingerprintManager#FINGERPRINT_ACQUIRED_PARTIAL}, + * {@link FingerprintManager#FINGERPRINT_ACQUIRED_INSUFFICIENT}, + * {@link FingerprintManager#FINGERPRINT_ACQUIRED_IMAGER_DIRTY}, + * {@link FingerprintManager#FINGERPRINT_ACQUIRED_TOO_SLOW}, + * {@link FingerprintManager#FINGERPRINT_ACQUIRED_TOO_FAST} */ - public void onScanned(int fingerprintId, int confidence) { } + public void onAcquired(int acquiredInfo) { } + + /** + * Fingerprint has been detected and processed. A non-zero return indicates a valid + * fingerprint was detected. + * + * @param fingerprintId the finger id, or 0 if not recognized. + */ + public void onProcessed(int fingerprintId) { } /** * 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_UNABLE_TO_PROCESS} or * {@link FingerprintManager#FINGERPRINT_ERROR_TIMEOUT} * {@link FingerprintManager#FINGERPRINT_ERROR_NO_SPACE} * diff --git a/core/java/android/service/fingerprint/FingerprintService.java b/core/java/android/service/fingerprint/FingerprintService.java deleted file mode 100644 index c7fa7cdadd08..000000000000 --- a/core/java/android/service/fingerprint/FingerprintService.java +++ /dev/null @@ -1,219 +0,0 @@ -/** - * 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); - } - } -} diff --git a/core/java/android/service/fingerprint/FingerprintUtils.java b/core/java/android/service/fingerprint/FingerprintUtils.java index 81a2aac5867b..f4b5526928c9 100644 --- a/core/java/android/service/fingerprint/FingerprintUtils.java +++ b/core/java/android/service/fingerprint/FingerprintUtils.java @@ -18,10 +18,12 @@ package android.service.fingerprint; import android.content.ContentResolver; import android.provider.Settings; +import android.text.TextUtils; import android.util.Log; import java.util.Arrays; +public class FingerprintUtils { private static final boolean DEBUG = true; private static final String TAG = "FingerprintUtils"; @@ -30,13 +32,16 @@ class FingerprintUtils { 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]); + int result[] = {}; + if (!TextUtils.isEmpty(fingerIdsRaw)) { + String[] fingerStringIds = fingerIdsRaw.replace("[","").replace("]","").split(", "); + 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; diff --git a/core/java/android/service/fingerprint/IFingerprintService.aidl b/core/java/android/service/fingerprint/IFingerprintService.aidl index e92c20cd0339..43d5e9a48d13 100644 --- a/core/java/android/service/fingerprint/IFingerprintService.aidl +++ b/core/java/android/service/fingerprint/IFingerprintService.aidl @@ -22,17 +22,20 @@ 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); +oneway interface IFingerprintService { + // Any errors resulting from this call will be returned to the listener + void enroll(IBinder token, long timeout, int userId); + + // Any errors resulting from this call will be returned to the listener + void enrollCancel(IBinder token, int userId); - // Returns 0 if fingerprintId's template can be removed, -1 otherwise - int remove(int fingerprintId, int userId); + // Any errors resulting from this call will be returned to the listener + void remove(IBinder token, 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); + void startListening(IBinder token, IFingerprintServiceReceiver receiver, int userId); // Stops listening for fingerprints - oneway void stopListening(int userId); + void stopListening(IBinder token, int userId); } diff --git a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl index 4826b59b650c..af4128f1122d 100644 --- a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl @@ -24,7 +24,8 @@ import android.os.UserHandle; */ oneway interface IFingerprintServiceReceiver { void onEnrollResult(int fingerprintId, int remaining); - void onScanned(int fingerprintId, int confidence); + void onAcquired(int acquiredInfo); + void onProcessed(int fingerprintId); void onError(int error); void onRemoved(int fingerprintId); } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index f2b9bac92a9f..a7a1faad41cb 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -159,6 +159,7 @@ extern int register_android_net_TrafficStats(JNIEnv* env); extern int register_android_text_AndroidCharacter(JNIEnv *env); extern int register_android_text_AndroidBidi(JNIEnv *env); extern int register_android_opengl_classes(JNIEnv *env); +extern int register_android_server_fingerprint_FingerprintService(JNIEnv* env); extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env); extern int register_android_server_Watchdog(JNIEnv* env); extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env); @@ -1328,6 +1329,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_media_ToneGenerator), REG_JNI(register_android_opengl_classes), + REG_JNI(register_android_server_fingerprint_FingerprintService), REG_JNI(register_android_server_NetworkManagementSocketTagger), REG_JNI(register_android_server_Watchdog), REG_JNI(register_android_ddm_DdmHandleNativeHeap), diff --git a/core/jni/android_server_FingerprintManager.cpp b/core/jni/android_server_FingerprintManager.cpp index f8a1fd9a4893..ad36843c764b 100644 --- a/core/jni/android_server_FingerprintManager.cpp +++ b/core/jni/android_server_FingerprintManager.cpp @@ -20,54 +20,195 @@ #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> +#include <hardware/hardware.h> +#include <hardware/fingerprint.h> #include <utils/Log.h> +#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); + namespace android { +static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(1, 0); + +static const char* FINGERPRINT_SERVICE = "com/android/server/fingerprint/FingerprintService"; static struct { jclass clazz; jmethodID notify; -} gFingerprintManagerClassInfo; + jobject callbackObject; +} gFingerprintServiceClassInfo; + +static struct { + fingerprint_module_t const* module; + fingerprint_device_t *device; +} gContext; + +// TODO: remove after driver update to use new HAL +fingerprint_msg_type_t hackTilFpDriverUpdate(fingerprint_msg_type_t t) { + switch(static_cast<int>(t)) { + case 1: return FINGERPRINT_PROCESSED; + case 2: return FINGERPRINT_TEMPLATE_ENROLLING; + default: return t; + } +} + +// Called by the HAL to notify us of fingerprint events +static void hal_notify_callback(fingerprint_msg_t msg) { + uint32_t arg1 = 0; + uint32_t arg2 = 0; + uint32_t arg3 = 0; // TODO + msg.type = hackTilFpDriverUpdate(msg.type); + switch (msg.type) { + case FINGERPRINT_ERROR: + arg1 = msg.data.error; + break; + case FINGERPRINT_ACQUIRED: + arg1 = msg.data.acquired.acquired_info; + break; + case FINGERPRINT_PROCESSED: + arg1 = msg.data.processed.id; + break; + case FINGERPRINT_TEMPLATE_ENROLLING: + arg1 = msg.data.enroll.id; + arg2 = msg.data.enroll.samples_remaining; + arg3 = msg.data.enroll.data_collected_bmp; + break; + case FINGERPRINT_TEMPLATE_REMOVED: + arg1 = msg.data.removed.id; + break; + default: + ALOGE("fingerprint: invalid msg: %d", msg.type); + return; + } + //ALOG(LOG_VERBOSE, LOG_TAG, "hal_notify(msg=%d, arg1=%d, arg2=%d)\n", msg.type, arg1, arg2); + + // TODO: fix gross hack to attach JNI to calling thread + JNIEnv* env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; + JavaVM* vm = AndroidRuntime::getJavaVM(); + int result = vm->AttachCurrentThread(&env, (void*) &args); + if (result != JNI_OK) { + ALOGE("Can't call JNI method: attach failed: %#x", result); + return; + } + } + env->CallVoidMethod(gFingerprintServiceClassInfo.callbackObject, + gFingerprintServiceClassInfo.notify, msg.type, arg1, arg2); +} + +static void nativeInit(JNIEnv *env, jobject clazz, jobject callbackObj) { + ALOG(LOG_VERBOSE, LOG_TAG, "nativeInit()\n"); + FIND_CLASS(gFingerprintServiceClassInfo.clazz, FINGERPRINT_SERVICE); + GET_METHOD_ID(gFingerprintServiceClassInfo.notify, gFingerprintServiceClassInfo.clazz, + "notify", "(III)V"); + gFingerprintServiceClassInfo.callbackObject = env->NewGlobalRef(callbackObj); +} static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) { - return -1; // TODO + ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll()\n"); + int ret = gContext.device->enroll(gContext.device, timeout); + return reinterpret_cast<jint>(ret); +} + +static jint nativeEnrollCancel(JNIEnv* env, jobject clazz) { + ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnrollCancel()\n"); + int ret = gContext.device->enroll_cancel(gContext.device); + return reinterpret_cast<jint>(ret); } static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) { - return -1; // TODO + ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(%d)\n", fingerprintId); + int ret = gContext.device->remove(gContext.device, fingerprintId); + return reinterpret_cast<jint>(ret); +} + +static jint nativeOpenHal(JNIEnv* env, jobject clazz) { + ALOG(LOG_VERBOSE, LOG_TAG, "nativeOpenHal()\n"); + int err; + const hw_module_t *hw_module = NULL; + if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) { + ALOGE("Can't open fingerprint HW Module, error: %d", err); + return 0; + } + if (NULL == hw_module) { + ALOGE("No valid fingerprint module"); + return 0; + } + + gContext.module = reinterpret_cast<const fingerprint_module_t*>(hw_module); + + if (gContext.module->common.methods->open == NULL) { + ALOGE("No valid open method"); + return 0; + } + + hw_device_t *device = NULL; + + if (0 != (err = gContext.module->common.methods->open(hw_module, NULL, &device))) { + ALOGE("Can't open fingerprint methods, error: %d", err); + return 0; + } + + if (kVersion != device->version) { + ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version); + // return 0; // FIXME + } + + gContext.device = reinterpret_cast<fingerprint_device_t*>(device); + err = gContext.device->set_notify(gContext.device, hal_notify_callback); + if (err < 0) { + ALOGE("Failed in call to set_notify(), err=%d", err); + return 0; + } + + // Sanity check - remove + if (gContext.device->notify != hal_notify_callback) { + ALOGE("NOTIFY not set properly: %p != %p", gContext.device->notify, hal_notify_callback); + } + + ALOG(LOG_VERBOSE, LOG_TAG, "fingerprint HAL successfully initialized"); + return reinterpret_cast<jlong>(gContext.device); +} + +static jint nativeCloseHal(JNIEnv* env, jobject clazz) { + return -ENOSYS; // TODO } // ---------------------------------------------------------------------------- +// TODO: clean up void methods static const JNINativeMethod g_methods[] = { { "nativeEnroll", "(I)I", (void*)nativeEnroll }, + { "nativeEnrollCancel", "()I", (void*)nativeEnroll }, { "nativeRemove", "(I)I", (void*)nativeRemove }, + { "nativeOpenHal", "()I", (void*)nativeOpenHal }, + { "nativeCloseHal", "()I", (void*)nativeCloseHal }, + { "nativeInit", "(Lcom/android/server/fingerprint/FingerprintService;)V", (void*)nativeInit } }; -#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)); +int register_android_server_fingerprint_FingerprintService(JNIEnv* env) { + FIND_CLASS(gFingerprintServiceClassInfo.clazz, FINGERPRINT_SERVICE); + GET_METHOD_ID(gFingerprintServiceClassInfo.notify, gFingerprintServiceClassInfo.clazz, "notify", + "(III)V"); + int result = AndroidRuntime::registerNativeMethods( + env, FINGERPRINT_SERVICE, g_methods, NELEM(g_methods)); + ALOG(LOG_VERBOSE, LOG_TAG, "FingerprintManager JNI ready.\n"); + return result; } } // namespace android diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java new file mode 100644 index 000000000000..29415745c3b8 --- /dev/null +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -0,0 +1,328 @@ +/** + * 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 com.android.server.fingerprint; + +import android.app.Service; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.PowerManager; +import android.os.RemoteException; +import android.provider.Settings; +import android.service.fingerprint.FingerprintManager; +import android.util.ArrayMap; +import android.util.Slog; + +import com.android.server.SystemService; + +import android.service.fingerprint.FingerprintUtils; +import android.service.fingerprint.IFingerprintService; +import android.service.fingerprint.IFingerprintServiceReceiver; + +import java.io.PrintWriter; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Set; + +/** + * 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 SystemService { + private final String TAG = "FingerprintService"; + private static final boolean DEBUG = true; + private ArrayMap<IBinder, ClientData> mClients = new ArrayMap<IBinder, 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 Context mContext; + + 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_REMOVING = 3; + private static final long MS_PER_SEC = 1000; + public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT"; + public static final String ENROLL_FINGERPRINT = "android.permission.ENROLL_FINGERPRINT"; + + private static final class ClientData { + public IFingerprintServiceReceiver receiver; + int state; + int userId; + public TokenWatcher tokenWatcher; + IBinder getToken() { return tokenWatcher.getToken(); } + } + + private class TokenWatcher implements IBinder.DeathRecipient { + WeakReference<IBinder> token; + + TokenWatcher(IBinder token) { + this.token = new WeakReference<IBinder>(token); + } + + IBinder getToken() { return token.get(); } + public void binderDied() { + mClients.remove(token); + this.token = null; + } + + protected void finalize() throws Throwable { + try { + if (token != null) { + if (DEBUG) Slog.w(TAG, "removing leaked reference: " + token); + mClients.remove(token); + } + } finally { + super.finalize(); + } + } + } + + public FingerprintService(Context context) { + super(context); + mContext = context; + nativeInit(this); + } + + // TODO: Move these into separate process + // JNI methods to communicate from FingerprintManagerService to HAL + native int nativeEnroll(int timeout); + native int nativeEnrollCancel(); + native int nativeRemove(int fingerprintId); + native int nativeOpenHal(); + native int nativeCloseHal(); + native void nativeInit(FingerprintService service); + + // 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) { + Slog.v(TAG, "handleNotify(msg=" + msg + ", arg1=" + arg1 + ", arg2=" + arg2 + ")"); + for (int i = 0; i < mClients.size(); i++) { + ClientData clientData = mClients.valueAt(i); + if (clientData == null || clientData.receiver == null) { + if (DEBUG) Slog.v(TAG, "clientData at " + i + " is invalid!!"); + continue; + } + switch (msg) { + case FingerprintManager.FINGERPRINT_ERROR: { + final int error = arg1; + try { + clientData.receiver.onError(error); + } catch (RemoteException e) { + Slog.e(TAG, "can't send message to client. Did it die?", e); + mClients.remove(mClients.keyAt(i)); + } + } + break; + case FingerprintManager.FINGERPRINT_ACQUIRED: { + final int acquireInfo = arg1; + try { + clientData.receiver.onAcquired(acquireInfo); + } catch (RemoteException e) { + Slog.e(TAG, "can't send message to client. Did it die?", e); + mClients.remove(mClients.keyAt(i)); + } + break; + } + case FingerprintManager.FINGERPRINT_PROCESSED: { + final int fingerId = arg1; + try { + clientData.receiver.onProcessed(fingerId); + } catch (RemoteException e) { + Slog.e(TAG, "can't send message to client. Did it die?", e); + mClients.remove(mClients.keyAt(i)); + } + break; + } + case FingerprintManager.FINGERPRINT_TEMPLATE_ENROLLING: { + final int fingerId = arg1; + final int remaining = arg2; + if (clientData.state == STATE_ENROLLING) { + // Only send enroll updates to clients that are actually enrolling + try { + clientData.receiver.onEnrollResult(fingerId, remaining); + } catch (RemoteException e) { + Slog.e(TAG, "can't send message to client. Did it die?", e); + mClients.remove(mClients.keyAt(i)); + } + // Update the database with new finger id. + // TODO: move to client code (Settings) + if (remaining == 0) { + FingerprintUtils.addFingerprintIdForUser(fingerId, + mContext.getContentResolver(), clientData.userId); + clientData.state = STATE_IDLE; // Nothing left to do + } + } else { + if (DEBUG) Slog.w(TAG, "Client not enrolling"); + break; + } + break; + } + case FingerprintManager.FINGERPRINT_TEMPLATE_REMOVED: { + int fingerId = arg1; + if (fingerId == 0) throw new IllegalStateException("Got illegal id from HAL"); + FingerprintUtils.removeFingerprintIdForUser(fingerId, + mContext.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); + mClients.remove(mClients.keyAt(i)); + } + } + clientData.state = STATE_LISTENING; + } + break; + } + } + } + + void startEnroll(IBinder token, long timeout, int userId) { + ClientData clientData = mClients.get(token); + if (clientData != null) { + if (clientData.userId != userId) throw new IllegalStateException("Bad user"); + clientData.state = STATE_ENROLLING; + nativeEnroll((int) (timeout / MS_PER_SEC)); + } else { + Slog.w(TAG, "enroll(): No listener registered"); + } + } + + void startEnrollCancel(IBinder token, int userId) { + ClientData clientData = mClients.get(token); + if (clientData != null) { + if (clientData.userId != userId) throw new IllegalStateException("Bad user"); + clientData.state = STATE_LISTENING; + nativeEnrollCancel(); + } else { + Slog.w(TAG, "enrollCancel(): No listener registered"); + } + } + + // Remove all fingerprints for the given user. + void startRemove(IBinder token, int fingerId, int userId) { + ClientData clientData = mClients.get(token); + if (clientData != null) { + if (clientData.userId != userId) throw new IllegalStateException("Bad user"); + clientData.state = STATE_REMOVING; + // The fingerprint id will be removed when we get confirmation from the HAL + int result = nativeRemove(fingerId); + if (result != 0) { + Slog.w(TAG, "Error removing fingerprint with id = " + fingerId); + } + } else { + Slog.w(TAG, "remove(" + token + "): No listener registered"); + } + } + + void addListener(IBinder token, IFingerprintServiceReceiver receiver, int userId) { + if (DEBUG) Slog.v(TAG, "startListening(" + receiver + ")"); + if (mClients.get(token) == null) { + ClientData clientData = new ClientData(); + clientData.state = STATE_LISTENING; + clientData.receiver = receiver; + clientData.userId = userId; + clientData.tokenWatcher = new TokenWatcher(token); + try { + token.linkToDeath(clientData.tokenWatcher, 0); + mClients.put(token, clientData); + } catch (RemoteException e) { + Slog.w(TAG, "caught remote exception in linkToDeath: ", e); + } + } else { + if (DEBUG) Slog.v(TAG, "listener already registered for " + token); + } + } + + void removeListener(IBinder token, int userId) { + if (DEBUG) Slog.v(TAG, "stopListening(" + token + ")"); + ClientData clientData = mClients.get(token); + if (clientData != null) { + token.unlinkToDeath(clientData.tokenWatcher, 0); + mClients.remove(token); + } else { + if (DEBUG) Slog.v(TAG, "listener not registered: " + token); + } + mClients.remove(token); + } + + void checkPermission(String permisison) { + // TODO + } + + private final class FingerprintServiceWrapper extends IFingerprintService.Stub { + @Override // Binder call + public void enroll(IBinder token, long timeout, int userId) { + checkPermission(ENROLL_FINGERPRINT); + startEnroll(token, timeout, userId); + } + + @Override // Binder call + public void enrollCancel(IBinder token,int userId) { + checkPermission(ENROLL_FINGERPRINT); + startEnrollCancel(token, userId); + } + + @Override // Binder call + public void remove(IBinder token, int fingerprintId, int userId) { + checkPermission(ENROLL_FINGERPRINT); // TODO: Maybe have another permission + startRemove(token, fingerprintId, userId); + } + + @Override // Binder call + public void startListening(IBinder token, IFingerprintServiceReceiver receiver, int userId) + { + checkPermission(USE_FINGERPRINT); + addListener(token, receiver, userId); + } + + @Override // Binder call + public void stopListening(IBinder token, int userId) { + checkPermission(USE_FINGERPRINT); + removeListener(token, userId); + } + } + + @Override + public void onStart() { + publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); + nativeOpenHal(); + } + +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 3102cce4ea79..5cccdd600828 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -44,6 +44,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.service.dreams.DreamService; +import android.service.fingerprint.FingerprintManager; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -63,6 +64,7 @@ import com.android.server.content.ContentService; import com.android.server.devicepolicy.DevicePolicyManagerService; import com.android.server.display.DisplayManagerService; import com.android.server.dreams.DreamManagerService; +import com.android.server.fingerprint.FingerprintService; import com.android.server.hdmi.HdmiControlService; import com.android.server.input.InputManagerService; import com.android.server.job.JobSchedulerService; @@ -989,11 +991,19 @@ public final class SystemServer { } try { + Slog.i(TAG, "Fingerprint Manager"); + mSystemServiceManager.startService(FingerprintService.class); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting FingerprintService", e); + } + + try { Slog.i(TAG, "BackgroundDexOptService"); new BackgroundDexOptService(context); } catch (Throwable e) { reportWtf("starting BackgroundDexOptService", e); } + } try { |