Loading core/java/android/hardware/fingerprint/FingerprintManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -517,7 +517,8 @@ public class FingerprintManager { if (mService != null) try { mEnrollmentCallback = callback; mService.enroll(mToken, token, userId, mServiceReceiver, flags); mService.enroll(mToken, token, userId, mServiceReceiver, flags, mContext.getOpPackageName()); } catch (RemoteException e) { Log.w(TAG, "Remote exception in enroll: ", e); if (callback != null) { Loading core/java/android/hardware/fingerprint/IFingerprintDaemon.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -35,4 +35,6 @@ interface IFingerprintDaemon { int closeHal(); void init(IFingerprintDaemonCallback callback); int postEnroll(); int enumerate(); int cancelEnumeration(); } core/java/android/hardware/fingerprint/IFingerprintService.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ interface IFingerprintService { // Start fingerprint enrollment void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver, int flags); int flags, String opPackageName); // Cancel enrollment in progress void cancelEnrollment(IBinder token); Loading services/core/java/com/android/server/fingerprint/AuthenticationClient.java 0 → 100644 +156 −0 Original line number Diff line number Diff line /** * 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.android.server.fingerprint; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import android.content.Context; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.IFingerprintDaemon; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.os.IBinder; import android.os.RemoteException; import android.system.ErrnoException; import android.util.Slog; /** * A class to keep track of the authentication state for a given client. */ public abstract class AuthenticationClient extends ClientMonitor { private long mOpId; public abstract boolean handleFailedAttempt(); public abstract void resetFailedAttempts(); public AuthenticationClient(Context context, long halDeviceId, IBinder token, IFingerprintServiceReceiver receiver, int userId, int groupId, long opId, boolean restricted, String owner) { super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner); mOpId = opId; } @Override public boolean onAuthenticated(int fingerId, int groupId) { boolean result = false; boolean authenticated = fingerId != 0; IFingerprintServiceReceiver receiver = getReceiver(); if (receiver != null) { try { MetricsLogger.action(getContext(), MetricsEvent.ACTION_FINGERPRINT_AUTH, authenticated); if (!authenticated) { receiver.onAuthenticationFailed(getHalDeviceId()); } else { if (DEBUG) { Slog.v(TAG, "onAuthenticated(owner=" + getOwnerString() + ", id=" + fingerId + ", gp=" + groupId + ")"); } Fingerprint fp = !getIsRestricted() ? new Fingerprint("" /* TODO */, groupId, fingerId, getHalDeviceId()) : null; receiver.onAuthenticationSucceeded(getHalDeviceId(), fp); } } catch (RemoteException e) { Slog.w(TAG, "Failed to notify Authenticated:", e); result = true; // client failed } } else { result = true; // client not listening } if (fingerId == 0) { if (receiver != null) { FingerprintUtils.vibrateFingerprintError(getContext()); } // allow system-defined limit of number of attempts before giving up result |= handleFailedAttempt(); } else { if (receiver != null) { FingerprintUtils.vibrateFingerprintSuccess(getContext()); } result |= true; // we have a valid fingerprint, done resetFailedAttempts(); } return result; } /** * Start authentication */ @Override public int start() { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "start authentication: no fingeprintd!"); return ERROR_ESRCH; } try { final int result = daemon.authenticate(mOpId, getGroupId()); if (result != 0) { Slog.w(TAG, "startAuthentication failed, result=" + result); onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); return result; } if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is authenticating..."); } catch (RemoteException e) { Slog.e(TAG, "startAuthentication failed", e); return ERROR_ESRCH; } return 0; // success } @Override public int stop(boolean initiatedByClient) { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "stopAuthentication: no fingeprintd!"); return ERROR_ESRCH; } try { final int result = daemon.cancelAuthentication(); if (result != 0) { Slog.w(TAG, "stopAuthentication failed, result=" + result); return result; } if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is no longer authenticating"); } catch (RemoteException e) { Slog.e(TAG, "stopAuthentication failed", e); return ERROR_ESRCH; } return 0; // success } @Override public boolean onEnrollResult(int fingerId, int groupId, int rem) { if (DEBUG) Slog.w(TAG, "onEnrollResult() called for authenticate!"); return true; // Invalid for Authenticate } @Override public boolean onRemoved(int fingerId, int groupId) { if (DEBUG) Slog.w(TAG, "onRemoved() called for authenticate!"); return true; // Invalid for Authenticate } @Override public boolean onEnumerationResult(int fingerId, int groupId) { if (DEBUG) Slog.w(TAG, "onEnumerationResult() called for authenticate!"); return true; // Invalid for Authenticate } } services/core/java/com/android/server/fingerprint/ClientMonitor.java 0 → 100644 +211 −0 Original line number Diff line number Diff line /** * 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.android.server.fingerprint; import android.Manifest; import android.content.Context; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.IFingerprintDaemon; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; import java.util.NoSuchElementException; /** * Abstract base class for keeping track and dispatching events from fingerprintd to the * the current client. Subclasses are responsible for coordinating the interaction with * fingerprintd for the specific action (e.g. authenticate, enroll, enumerate, etc.). */ public abstract class ClientMonitor implements IBinder.DeathRecipient { protected static final String TAG = FingerprintService.TAG; // TODO: get specific name protected static final int ERROR_ESRCH = 3; // Likely fingerprintd is dead. See errno.h. protected static final boolean DEBUG = FingerprintService.DEBUG; private IBinder mToken; private IFingerprintServiceReceiver mReceiver; private int mUserId; private int mGroupId; private boolean mIsRestricted; // True if client does not have MANAGE_FINGERPRINT permission private String mOwner; private Context mContext; private long mHalDeviceId; /** * @param context context of FingerprintService * @param halDeviceId the HAL device ID of the associated fingerprint hardware * @param token a unique token for the client * @param receiver recipient of related events (e.g. authentication) * @param userId userId for the fingerprint set * @param groupId groupId for the fingerprint set * @param restricted whether or not client has the {@link Manifest#MANAGE_FINGERPRINT} * permission * @param owner name of the client that owns this */ public ClientMonitor(Context context, long halDeviceId, IBinder token, IFingerprintServiceReceiver receiver, int userId, int groupId,boolean restricted, String owner) { mContext = context; mHalDeviceId = halDeviceId; mToken = token; mReceiver = receiver; mUserId = userId; mGroupId = groupId; mIsRestricted = restricted; mOwner = owner; try { token.linkToDeath(this, 0); } catch (RemoteException e) { Slog.w(TAG, "caught remote exception in linkToDeath: ", e); } } /** * Contacts fingerprintd to start the client. * @return 0 on succes, errno from driver on failure */ public abstract int start(); /** * Contacts fingerprintd to stop the client. * @param initiatedByClient whether the operation is at the request of a client */ public abstract int stop(boolean initiatedByClient); /** * Method to explicitly poke powermanager on events */ public abstract void notifyUserActivity(); /** * Gets the fingerprint daemon from the cached state in the container class. */ public abstract IFingerprintDaemon getFingerprintDaemon(); // Event callbacks from driver. Inappropriate calls is flagged/logged by the // respective client (e.g. enrolling shouldn't get authenticate events). // All of these return 'true' if the operation is completed and it's ok to move // to the next client (e.g. authentication accepts or rejects a fingerprint). public abstract boolean onEnrollResult(int fingerId, int groupId, int rem); public abstract boolean onAuthenticated(int fingerId, int groupId); public abstract boolean onRemoved(int fingerId, int groupId); public abstract boolean onEnumerationResult(int fingerId, int groupId); /** * Called when we get notification from fingerprintd that an image has been acquired. * Common to authenticate and enroll. * @param acquiredInfo info about the current image acquisition * @return true if client should be removed */ public boolean onAcquired(int acquiredInfo) { if (mReceiver == null) return true; // client not connected try { mReceiver.onAcquired(getHalDeviceId(), acquiredInfo); return false; // acquisition continues... } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke sendAcquired:", e); return true; // client failed } finally { // Good scans will keep the device awake if (acquiredInfo == FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) { notifyUserActivity(); } } } /** * Called when we get notification from fingerprintd that an error has occurred with the * current operation. Common to authenticate, enroll, enumerate and remove. * @param error * @return true if client should be removed */ public boolean onError(int error) { if (mReceiver != null) { try { mReceiver.onError(getHalDeviceId(), error); } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke sendError:", e); } } return true; // errors always remove current client } public void destroy() { if (mToken != null) { try { mToken.unlinkToDeath(this, 0); } catch (NoSuchElementException e) { // TODO: remove when duplicate call bug is found Slog.e(TAG, "destroy(): " + this + ":", new Exception("here")); } mToken = null; } mReceiver = null; } @Override public void binderDied() { mToken = null; mReceiver = null; onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); } @Override protected void finalize() throws Throwable { try { if (mToken != null) { if (DEBUG) Slog.w(TAG, "removing leaked reference: " + mToken); onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); } } finally { super.finalize(); } } public final Context getContext() { return mContext; } public final long getHalDeviceId() { return mHalDeviceId; } public final String getOwnerString() { return mOwner; } public final IFingerprintServiceReceiver getReceiver() { return mReceiver; } public final boolean getIsRestricted() { return mIsRestricted; } public final int getUserId() { return mUserId; } public final int getGroupId() { return mGroupId; } public final IBinder getToken() { return mToken; } } Loading
core/java/android/hardware/fingerprint/FingerprintManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -517,7 +517,8 @@ public class FingerprintManager { if (mService != null) try { mEnrollmentCallback = callback; mService.enroll(mToken, token, userId, mServiceReceiver, flags); mService.enroll(mToken, token, userId, mServiceReceiver, flags, mContext.getOpPackageName()); } catch (RemoteException e) { Log.w(TAG, "Remote exception in enroll: ", e); if (callback != null) { Loading
core/java/android/hardware/fingerprint/IFingerprintDaemon.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -35,4 +35,6 @@ interface IFingerprintDaemon { int closeHal(); void init(IFingerprintDaemonCallback callback); int postEnroll(); int enumerate(); int cancelEnumeration(); }
core/java/android/hardware/fingerprint/IFingerprintService.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ interface IFingerprintService { // Start fingerprint enrollment void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver, int flags); int flags, String opPackageName); // Cancel enrollment in progress void cancelEnrollment(IBinder token); Loading
services/core/java/com/android/server/fingerprint/AuthenticationClient.java 0 → 100644 +156 −0 Original line number Diff line number Diff line /** * 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.android.server.fingerprint; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import android.content.Context; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.IFingerprintDaemon; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.os.IBinder; import android.os.RemoteException; import android.system.ErrnoException; import android.util.Slog; /** * A class to keep track of the authentication state for a given client. */ public abstract class AuthenticationClient extends ClientMonitor { private long mOpId; public abstract boolean handleFailedAttempt(); public abstract void resetFailedAttempts(); public AuthenticationClient(Context context, long halDeviceId, IBinder token, IFingerprintServiceReceiver receiver, int userId, int groupId, long opId, boolean restricted, String owner) { super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner); mOpId = opId; } @Override public boolean onAuthenticated(int fingerId, int groupId) { boolean result = false; boolean authenticated = fingerId != 0; IFingerprintServiceReceiver receiver = getReceiver(); if (receiver != null) { try { MetricsLogger.action(getContext(), MetricsEvent.ACTION_FINGERPRINT_AUTH, authenticated); if (!authenticated) { receiver.onAuthenticationFailed(getHalDeviceId()); } else { if (DEBUG) { Slog.v(TAG, "onAuthenticated(owner=" + getOwnerString() + ", id=" + fingerId + ", gp=" + groupId + ")"); } Fingerprint fp = !getIsRestricted() ? new Fingerprint("" /* TODO */, groupId, fingerId, getHalDeviceId()) : null; receiver.onAuthenticationSucceeded(getHalDeviceId(), fp); } } catch (RemoteException e) { Slog.w(TAG, "Failed to notify Authenticated:", e); result = true; // client failed } } else { result = true; // client not listening } if (fingerId == 0) { if (receiver != null) { FingerprintUtils.vibrateFingerprintError(getContext()); } // allow system-defined limit of number of attempts before giving up result |= handleFailedAttempt(); } else { if (receiver != null) { FingerprintUtils.vibrateFingerprintSuccess(getContext()); } result |= true; // we have a valid fingerprint, done resetFailedAttempts(); } return result; } /** * Start authentication */ @Override public int start() { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "start authentication: no fingeprintd!"); return ERROR_ESRCH; } try { final int result = daemon.authenticate(mOpId, getGroupId()); if (result != 0) { Slog.w(TAG, "startAuthentication failed, result=" + result); onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); return result; } if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is authenticating..."); } catch (RemoteException e) { Slog.e(TAG, "startAuthentication failed", e); return ERROR_ESRCH; } return 0; // success } @Override public int stop(boolean initiatedByClient) { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "stopAuthentication: no fingeprintd!"); return ERROR_ESRCH; } try { final int result = daemon.cancelAuthentication(); if (result != 0) { Slog.w(TAG, "stopAuthentication failed, result=" + result); return result; } if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is no longer authenticating"); } catch (RemoteException e) { Slog.e(TAG, "stopAuthentication failed", e); return ERROR_ESRCH; } return 0; // success } @Override public boolean onEnrollResult(int fingerId, int groupId, int rem) { if (DEBUG) Slog.w(TAG, "onEnrollResult() called for authenticate!"); return true; // Invalid for Authenticate } @Override public boolean onRemoved(int fingerId, int groupId) { if (DEBUG) Slog.w(TAG, "onRemoved() called for authenticate!"); return true; // Invalid for Authenticate } @Override public boolean onEnumerationResult(int fingerId, int groupId) { if (DEBUG) Slog.w(TAG, "onEnumerationResult() called for authenticate!"); return true; // Invalid for Authenticate } }
services/core/java/com/android/server/fingerprint/ClientMonitor.java 0 → 100644 +211 −0 Original line number Diff line number Diff line /** * 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.android.server.fingerprint; import android.Manifest; import android.content.Context; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.IFingerprintDaemon; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; import java.util.NoSuchElementException; /** * Abstract base class for keeping track and dispatching events from fingerprintd to the * the current client. Subclasses are responsible for coordinating the interaction with * fingerprintd for the specific action (e.g. authenticate, enroll, enumerate, etc.). */ public abstract class ClientMonitor implements IBinder.DeathRecipient { protected static final String TAG = FingerprintService.TAG; // TODO: get specific name protected static final int ERROR_ESRCH = 3; // Likely fingerprintd is dead. See errno.h. protected static final boolean DEBUG = FingerprintService.DEBUG; private IBinder mToken; private IFingerprintServiceReceiver mReceiver; private int mUserId; private int mGroupId; private boolean mIsRestricted; // True if client does not have MANAGE_FINGERPRINT permission private String mOwner; private Context mContext; private long mHalDeviceId; /** * @param context context of FingerprintService * @param halDeviceId the HAL device ID of the associated fingerprint hardware * @param token a unique token for the client * @param receiver recipient of related events (e.g. authentication) * @param userId userId for the fingerprint set * @param groupId groupId for the fingerprint set * @param restricted whether or not client has the {@link Manifest#MANAGE_FINGERPRINT} * permission * @param owner name of the client that owns this */ public ClientMonitor(Context context, long halDeviceId, IBinder token, IFingerprintServiceReceiver receiver, int userId, int groupId,boolean restricted, String owner) { mContext = context; mHalDeviceId = halDeviceId; mToken = token; mReceiver = receiver; mUserId = userId; mGroupId = groupId; mIsRestricted = restricted; mOwner = owner; try { token.linkToDeath(this, 0); } catch (RemoteException e) { Slog.w(TAG, "caught remote exception in linkToDeath: ", e); } } /** * Contacts fingerprintd to start the client. * @return 0 on succes, errno from driver on failure */ public abstract int start(); /** * Contacts fingerprintd to stop the client. * @param initiatedByClient whether the operation is at the request of a client */ public abstract int stop(boolean initiatedByClient); /** * Method to explicitly poke powermanager on events */ public abstract void notifyUserActivity(); /** * Gets the fingerprint daemon from the cached state in the container class. */ public abstract IFingerprintDaemon getFingerprintDaemon(); // Event callbacks from driver. Inappropriate calls is flagged/logged by the // respective client (e.g. enrolling shouldn't get authenticate events). // All of these return 'true' if the operation is completed and it's ok to move // to the next client (e.g. authentication accepts or rejects a fingerprint). public abstract boolean onEnrollResult(int fingerId, int groupId, int rem); public abstract boolean onAuthenticated(int fingerId, int groupId); public abstract boolean onRemoved(int fingerId, int groupId); public abstract boolean onEnumerationResult(int fingerId, int groupId); /** * Called when we get notification from fingerprintd that an image has been acquired. * Common to authenticate and enroll. * @param acquiredInfo info about the current image acquisition * @return true if client should be removed */ public boolean onAcquired(int acquiredInfo) { if (mReceiver == null) return true; // client not connected try { mReceiver.onAcquired(getHalDeviceId(), acquiredInfo); return false; // acquisition continues... } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke sendAcquired:", e); return true; // client failed } finally { // Good scans will keep the device awake if (acquiredInfo == FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) { notifyUserActivity(); } } } /** * Called when we get notification from fingerprintd that an error has occurred with the * current operation. Common to authenticate, enroll, enumerate and remove. * @param error * @return true if client should be removed */ public boolean onError(int error) { if (mReceiver != null) { try { mReceiver.onError(getHalDeviceId(), error); } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke sendError:", e); } } return true; // errors always remove current client } public void destroy() { if (mToken != null) { try { mToken.unlinkToDeath(this, 0); } catch (NoSuchElementException e) { // TODO: remove when duplicate call bug is found Slog.e(TAG, "destroy(): " + this + ":", new Exception("here")); } mToken = null; } mReceiver = null; } @Override public void binderDied() { mToken = null; mReceiver = null; onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); } @Override protected void finalize() throws Throwable { try { if (mToken != null) { if (DEBUG) Slog.w(TAG, "removing leaked reference: " + mToken); onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); } } finally { super.finalize(); } } public final Context getContext() { return mContext; } public final long getHalDeviceId() { return mHalDeviceId; } public final String getOwnerString() { return mOwner; } public final IFingerprintServiceReceiver getReceiver() { return mReceiver; } public final boolean getIsRestricted() { return mIsRestricted; } public final int getUserId() { return mUserId; } public final int getGroupId() { return mGroupId; } public final IBinder getToken() { return mToken; } }