几个路径:

/frameworks/base/services/core/java/com/android/server/fingerprint/

/frameworks/base/core/java/android/hardware/fingerprint/

/system/core/fingerprintd/

/hardware/libhardware/include/hardware/fingerprint.h

/hardware/libhardware/modules/fingerprint/fingerprint.c

====================================================

Android M 指纹框架_第1张图片

/frameworks/base/services/core/java/com/android/server/fingerprint/

-------------------------------------------------------------------------------------------

FingerprintService.java

/** * 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.ActivityManager;import android.app.ActivityManagerNative;import android.app.AppOpsManager;import android.app.IUserSwitchObserver;import android.content.ContentResolver;import android.content.Context;import android.content.pm.PackageManager;import android.content.pm.UserInfo;import android.os.Binder;import android.os.Environment;import android.os.Handler;import android.os.IBinder;import android.os.IRemoteCallback;import android.os.Looper;import android.os.MessageQueue;import android.os.PowerManager;import android.os.RemoteException;import android.os.SELinux;import android.os.ServiceManager;import android.os.SystemClock;import android.os.UserHandle;import android.os.UserManager;import android.util.Slog;import com.android.server.SystemService;import android.hardware.fingerprint.Fingerprint;import android.hardware.fingerprint.FingerprintManager;import android.hardware.fingerprint.IFingerprintService;import android.hardware.fingerprint.IFingerprintDaemon;import android.hardware.fingerprint.IFingerprintDaemonCallback;import android.hardware.fingerprint.IFingerprintServiceReceiver;import static android.Manifest.permission.MANAGE_FINGERPRINT;import static android.Manifest.permission.USE_FINGERPRINT;import java.io.File;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.List;import java.util.NoSuchElementException;/** * 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 implements IBinder.DeathRecipient {    private static final String TAG = "FingerprintService";    private static final boolean DEBUG = true;    private static final String FP_DATA_DIR = "fpdata";    private static final String FINGERPRINTD = "android.hardware.fingerprint.IFingerprintDaemon";    private static final int MSG_USER_SWITCHING = 10;    private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute    private ClientMonitor mAuthClient = null;    private ClientMonitor mEnrollClient = null;    private ClientMonitor mRemoveClient = null;    private final AppOpsManager mAppOps;    private static final long MS_PER_SEC = 1000;    private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;    private static final int MAX_FAILED_ATTEMPTS = 5;    private static final int FINGERPRINT_ACQUIRED_GOOD = 0;    Handler mHandler = new Handler() {        @Override        public void handleMessage(android.os.Message msg) {            switch (msg.what) {                case MSG_USER_SWITCHING:                    handleUserSwitching(msg.arg1);                    break;                default:                    Slog.w(TAG, "Unknown message:" + msg.what);            }        }    };    private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();    private Context mContext;    private long mHalDeviceId;    private int mFailedAttempts;    private IFingerprintDaemon mDaemon;    private PowerManager mPowerManager;    private final Runnable mLockoutReset = new Runnable() {        @Override        public void run() {            resetFailedAttempts();        }    };    public FingerprintService(Context context) {        super(context);        mContext = context;        mAppOps = context.getSystemService(AppOpsManager.class);        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);    }    @Override    public void binderDied() {        Slog.v(TAG, "fingerprintd died");        mDaemon = null;        dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);    }    public IFingerprintDaemon getFingerprintDaemon() {        if (mDaemon == null) {            mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD));            if (mDaemon != null) {                try {                    mDaemon.asBinder().linkToDeath(this, 0);                    mDaemon.init(mDaemonCallback);                    mHalDeviceId = mDaemon.openHal();                    if (mHalDeviceId != 0) {                        updateActiveGroup(ActivityManager.getCurrentUser());                    } else {                        Slog.w(TAG, "Failed to open Fingerprint HAL!");                        mDaemon = null;                    }                } catch (RemoteException e) {                    Slog.e(TAG, "Failed to open fingeprintd HAL", e);                    mDaemon = null; // try again later!                }            } else {                Slog.w(TAG, "fingerprint service not available");            }        }        return mDaemon;    }    protected void dispatchEnumerate(long deviceId, int[] fingerIds, int[] groupIds) {        if (fingerIds.length != groupIds.length) {            Slog.w(TAG, "fingerIds and groupIds differ in length: f[]="                    + fingerIds + ", g[]=" + groupIds);            return;        }        if (DEBUG) Slog.w(TAG, "Enumerate: f[]=" + fingerIds + ", g[]=" + groupIds);        // TODO: update fingerprint/name pairs    }    protected void dispatchRemoved(long deviceId, int fingerId, int groupId) {        final ClientMonitor client = mRemoveClient;        if (fingerId != 0) {            removeTemplateForUser(mRemoveClient, fingerId);        }        if (client != null && client.sendRemoved(fingerId, groupId)) {            removeClient(mRemoveClient);        }    }    protected void dispatchError(long deviceId, int error) {        if (mEnrollClient != null) {            final IBinder token = mEnrollClient.token;            if (mEnrollClient.sendError(error)) {                stopEnrollment(token, false);            }        } else if (mAuthClient != null) {            final IBinder token = mAuthClient.token;            if (mAuthClient.sendError(error)) {                stopAuthentication(token, false);            }        } else if (mRemoveClient != null) {            if (mRemoveClient.sendError(error)) removeClient(mRemoveClient);        }    }    protected void dispatchAuthenticated(long deviceId, int fingerId, int groupId) {        if (mAuthClient != null) {            final IBinder token = mAuthClient.token;            if (mAuthClient.sendAuthenticated(fingerId, groupId)) {                stopAuthentication(token, false);                removeClient(mAuthClient);            }        }    }    protected void dispatchAcquired(long deviceId, int acquiredInfo) {        if (mEnrollClient != null) {            if (mEnrollClient.sendAcquired(acquiredInfo)) {                removeClient(mEnrollClient);            }        } else if (mAuthClient != null) {            if (mAuthClient.sendAcquired(acquiredInfo)) {                removeClient(mAuthClient);            }        }    }    private void userActivity() {        long now = SystemClock.uptimeMillis();        mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);    }    void handleUserSwitching(int userId) {        updateActiveGroup(userId);    }    protected void dispatchEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {        if (mEnrollClient != null) {            if (mEnrollClient.sendEnrollResult(fingerId, groupId, remaining)) {                if (remaining == 0) {                    addTemplateForUser(mEnrollClient, fingerId);                    removeClient(mEnrollClient);                }            }        }    }    private void removeClient(ClientMonitor client) {        if (client == null) return;        client.destroy();        if (client == mAuthClient) {            mAuthClient = null;        } else if (client == mEnrollClient) {            mEnrollClient = null;        } else if (client == mRemoveClient) {            mRemoveClient = null;        }    }    private boolean inLockoutMode() {        return mFailedAttempts > MAX_FAILED_ATTEMPTS;    }    private void resetFailedAttempts() {        if (DEBUG && inLockoutMode()) {            Slog.v(TAG, "Reset fingerprint lockout");        }        mFailedAttempts = 0;    }    private boolean handleFailedAttempt(ClientMonitor clientMonitor) {        mFailedAttempts++;        if (mFailedAttempts > MAX_FAILED_ATTEMPTS) {            // Failing multiple times will continue to push out the lockout time.            mHandler.removeCallbacks(mLockoutReset);            mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS);            if (clientMonitor != null                    && !clientMonitor.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {                Slog.w(TAG, "Cannot send lockout message to client");            }            return true;        }        return false;    }    private void removeTemplateForUser(ClientMonitor clientMonitor, int fingerId) {        mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, clientMonitor.userId);    }    private void addTemplateForUser(ClientMonitor clientMonitor, int fingerId) {        mFingerprintUtils.addFingerprintForUser(mContext, fingerId, clientMonitor.userId);    }    void startEnrollment(IBinder token, byte[] cryptoToken, int groupId,            IFingerprintServiceReceiver receiver, int flags, boolean restricted) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon == null) {            Slog.w(TAG, "enroll: no fingeprintd!");            return;        }        stopPendingOperations(true);        mEnrollClient = new ClientMonitor(token, receiver, groupId, restricted);        final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);        try {            final int result = daemon.enroll(cryptoToken, groupId, timeout);            if (result != 0) {                Slog.w(TAG, "startEnroll failed, result=" + result);            }        } catch (RemoteException e) {            Slog.e(TAG, "startEnroll failed", e);        }    }    public long startPreEnroll(IBinder token) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon == null) {            Slog.w(TAG, "startPreEnroll: no fingeprintd!");            return 0;        }        try {            return daemon.preEnroll();        } catch (RemoteException e) {            Slog.e(TAG, "startPreEnroll failed", e);        }        return 0;    }    public int startPostEnroll(IBinder token) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon == null) {            Slog.w(TAG, "startPostEnroll: no fingeprintd!");            return 0;        }        try {            return daemon.postEnroll();        } catch (RemoteException e) {            Slog.e(TAG, "startPostEnroll failed", e);        }        return 0;    }    private void stopPendingOperations(boolean initiatedByClient) {        if (mEnrollClient != null) {            stopEnrollment(mEnrollClient.token, initiatedByClient);        }        if (mAuthClient != null) {            stopAuthentication(mAuthClient.token, initiatedByClient);        }        // mRemoveClient is allowed to continue    }    /**     * Stop enrollment in progress and inform client if they initiated it.     *     * @param token token for client     * @param initiatedByClient if this call is the result of client action (e.g. calling cancel)     */    void stopEnrollment(IBinder token, boolean initiatedByClient) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon == null) {            Slog.w(TAG, "stopEnrollment: no fingeprintd!");            return;        }        final ClientMonitor client = mEnrollClient;        if (client == null || client.token != token) return;        if (initiatedByClient) {            try {                int result = daemon.cancelEnrollment();                if (result != 0) {                    Slog.w(TAG, "startEnrollCancel failed, result = " + result);                }            } catch (RemoteException e) {                Slog.e(TAG, "stopEnrollment failed", e);            }            client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);        }        removeClient(mEnrollClient);    }    void startAuthentication(IBinder token, long opId, int groupId,            IFingerprintServiceReceiver receiver, int flags, boolean restricted) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon == null) {            Slog.w(TAG, "startAuthentication: no fingeprintd!");            return;        }        stopPendingOperations(true);        mAuthClient = new ClientMonitor(token, receiver, groupId, restricted);        if (inLockoutMode()) {            Slog.v(TAG, "In lockout mode; disallowing authentication");            if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {                Slog.w(TAG, "Cannot send timeout message to client");            }            mAuthClient = null;            return;        }        try {            final int result = daemon.authenticate(opId, groupId);            if (result != 0) {                Slog.w(TAG, "startAuthentication failed, result=" + result);            }        } catch (RemoteException e) {            Slog.e(TAG, "startAuthentication failed", e);        }    }    /**     * Stop authentication in progress and inform client if they initiated it.     *     * @param token token for client     * @param initiatedByClient if this call is the result of client action (e.g. calling cancel)     */    void stopAuthentication(IBinder token, boolean initiatedByClient) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon == null) {            Slog.w(TAG, "stopAuthentication: no fingeprintd!");            return;        }        final ClientMonitor client = mAuthClient;        if (client == null || client.token != token) return;        if (initiatedByClient) {            try {                int result = daemon.cancelAuthentication();                if (result != 0) {                    Slog.w(TAG, "stopAuthentication failed, result=" + result);                }            } catch (RemoteException e) {                Slog.e(TAG, "stopAuthentication failed", e);            }            client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);        }        removeClient(mAuthClient);    }    void startRemove(IBinder token, int fingerId, int userId,            IFingerprintServiceReceiver receiver, boolean restricted) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon == null) {            Slog.w(TAG, "startRemove: no fingeprintd!");            return;        }        mRemoveClient = new ClientMonitor(token, receiver, userId, restricted);        // The fingerprint template ids will be removed when we get confirmation from the HAL        try {            final int result = daemon.remove(fingerId, userId);            if (result != 0) {                Slog.w(TAG, "startRemove with id = " + fingerId + " failed, result=" + result);            }        } catch (RemoteException e) {            Slog.e(TAG, "startRemove failed", e);        }    }    public List getEnrolledFingerprints(int userId) {        return mFingerprintUtils.getFingerprintsForUser(mContext, userId);    }    public boolean hasEnrolledFingerprints(int userId) {        return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0;    }    boolean hasPermission(String permission) {        return getContext().checkCallingOrSelfPermission(permission)                == PackageManager.PERMISSION_GRANTED;    }    void checkPermission(String permission) {        getContext().enforceCallingOrSelfPermission(permission,                "Must have " + permission + " permission.");    }    int getEffectiveUserId(int userId) {        UserManager um = UserManager.get(mContext);        if (um != null) {            final long callingIdentity = Binder.clearCallingIdentity();            userId = um.getCredentialOwnerProfile(userId);            Binder.restoreCallingIdentity(callingIdentity);        } else {            Slog.e(TAG, "Unable to acquire UserManager");        }        return userId;    }    boolean isCurrentUserOrProfile(int userId) {        UserManager um = UserManager.get(mContext);        // Allow current user or profiles of the current user...        List profiles = um.getEnabledProfiles(userId);        final int n = profiles.size();        for (int i = 0; i < n; i++) {            if (profiles.get(i).id == userId) {                return true;            }        }        return false;    }    private boolean canUseFingerprint(String opPackageName) {        checkPermission(USE_FINGERPRINT);        return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(),                opPackageName) == AppOpsManager.MODE_ALLOWED;    }    private class ClientMonitor implements IBinder.DeathRecipient {        IBinder token;        IFingerprintServiceReceiver receiver;        int userId;        boolean restricted; // True if client does not have MANAGE_FINGERPRINT permission        public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId,                boolean restricted) {            this.token = token;            this.receiver = receiver;            this.userId = userId;            this.restricted = restricted;            try {                token.linkToDeath(this, 0);            } catch (RemoteException e) {                Slog.w(TAG, "caught remote exception in linkToDeath: ", e);            }        }        public void destroy() {            if (token != null) {                try {                    token.unlinkToDeath(this, 0);                } catch (NoSuchElementException e) {                    // TODO: remove when duplicate call bug is found                    Slog.e(TAG, "destroy(): " + this + ":", new Exception("here"));                }                token = null;            }            receiver = null;        }        @Override        public void binderDied() {            token = null;            removeClient(this);            receiver = null;        }        @Override        protected void finalize() throws Throwable {            try {                if (token != null) {                    if (DEBUG) Slog.w(TAG, "removing leaked reference: " + token);                    removeClient(this);                }            } finally {                super.finalize();            }        }        /*         * @return true if we're done.         */        private boolean sendRemoved(int fingerId, int groupId) {            if (receiver == null) return true; // client not listening            try {                receiver.onRemoved(mHalDeviceId, fingerId, groupId);                return fingerId == 0;            } catch (RemoteException e) {                Slog.w(TAG, "Failed to notify Removed:", e);            }            return false;        }        /*         * @return true if we're done.         */        private boolean sendEnrollResult(int fpId, int groupId, int remaining) {            if (receiver == null) return true; // client not listening            FingerprintUtils.vibrateFingerprintSuccess(getContext());            try {                receiver.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);                return remaining == 0;            } catch (RemoteException e) {                Slog.w(TAG, "Failed to notify EnrollResult:", e);                return true;            }        }        /*         * @return true if we're done.         */        private boolean sendAuthenticated(int fpId, int groupId) {            boolean result = false;            boolean authenticated = fpId != 0;            if (receiver != null) {                try {                    if (!authenticated) {                        receiver.onAuthenticationFailed(mHalDeviceId);                    } else {                        Fingerprint fp = !restricted ?                                new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null;                        receiver.onAuthenticationSucceeded(mHalDeviceId, fp);                    }                } catch (RemoteException e) {                    Slog.w(TAG, "Failed to notify Authenticated:", e);                    result = true; // client failed                }            } else {                result = true; // client not listening    }    if (fpId == 0) {                FingerprintUtils.vibrateFingerprintError(getContext());                result |= handleFailedAttempt(this);            } else {                FingerprintUtils.vibrateFingerprintSuccess(getContext());                result |= true; // we have a valid fingerprint                mLockoutReset.run();            }            return result;        }        /*         * @return true if we're done.         */        private boolean sendAcquired(int acquiredInfo) {            if (receiver == null) return true; // client not listening            try {                receiver.onAcquired(mHalDeviceId, 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 == FINGERPRINT_ACQUIRED_GOOD) {                    userActivity();                }            }        }        /*         * @return true if we're done.         */        private boolean sendError(int error) {            if (receiver != null) {                try {                    receiver.onError(mHalDeviceId, error);                } catch (RemoteException e) {                    Slog.w(TAG, "Failed to invoke sendError:", e);                }            }            return true; // errors always terminate progress        }    }    private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() {        @Override        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {            dispatchEnrollResult(deviceId, fingerId, groupId, remaining);        }        @Override        public void onAcquired(long deviceId, int acquiredInfo) {            dispatchAcquired(deviceId, acquiredInfo);        }        @Override        public void onAuthenticated(long deviceId, int fingerId, int groupId) {            dispatchAuthenticated(deviceId, fingerId, groupId);        }        @Override        public void onError(long deviceId, int error) {            dispatchError(deviceId, error);        }        @Override        public void onRemoved(long deviceId, int fingerId, int groupId) {            dispatchRemoved(deviceId, fingerId, groupId);        }        @Override        public void onEnumerate(long deviceId, int[] fingerIds, int[] groupIds) {            dispatchEnumerate(deviceId, fingerIds, groupIds);        }    };    private final class FingerprintServiceWrapper extends IFingerprintService.Stub {        private static final String KEYGUARD_PACKAGE = "com.android.systemui";        @Override // Binder call        public long preEnroll(IBinder token) {            checkPermission(MANAGE_FINGERPRINT);            return startPreEnroll(token);        }        @Override // Binder call        public int postEnroll(IBinder token) {            checkPermission(MANAGE_FINGERPRINT);            return startPostEnroll(token);        }        @Override // Binder call        public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId,                final IFingerprintServiceReceiver receiver, final int flags) {            checkPermission(MANAGE_FINGERPRINT);            final int limit =  mContext.getResources().getInteger(                    com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);            final int callingUid = Binder.getCallingUid();            final int userId = UserHandle.getUserId(callingUid);            final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();            if (enrolled >= limit) {                Slog.w(TAG, "Too many fingerprints registered");                return;            }            final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length);            // Group ID is arbitrarily set to parent profile user ID. It just represents            // the default fingerprints for the user.            final int effectiveGroupId = getEffectiveUserId(groupId);            final boolean restricted = isRestricted();            mHandler.post(new Runnable() {                @Override                public void run() {                    startEnrollment(token, cryptoClone, effectiveGroupId, receiver, flags, restricted);                }            });        }        private boolean isRestricted() {            // Only give privileged apps (like Settings) access to fingerprint info            final boolean restricted = !hasPermission(MANAGE_FINGERPRINT);            return restricted;        }        @Override // Binder call        public void cancelEnrollment(final IBinder token) {            checkPermission(MANAGE_FINGERPRINT);            mHandler.post(new Runnable() {                @Override                public void run() {                    stopEnrollment(token, true);                }            });        }        @Override // Binder call        public void authenticate(final IBinder token, final long opId, final int groupId,                final IFingerprintServiceReceiver receiver, final int flags,                final String opPackageName) {            if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) {                Slog.w(TAG, "Can't authenticate non-current user");                return;            }            if (!canUseFingerprint(opPackageName)) {                Slog.w(TAG, "Calling not granted permission to use fingerprint");                return;            }            // Group ID is arbitrarily set to parent profile user ID. It just represents            // the default fingerprints for the user.            final int effectiveGroupId = getEffectiveUserId(groupId);            final boolean restricted = isRestricted();            mHandler.post(new Runnable() {                @Override                public void run() {                    startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted);                }            });        }        @Override // Binder call        public void cancelAuthentication(final IBinder token, String opPackageName) {            if (!canUseFingerprint(opPackageName)) {                return;            }            mHandler.post(new Runnable() {                @Override                public void run() {                    stopAuthentication(token, true);                }            });        }        @Override // Binder call        public void remove(final IBinder token, final int fingerId, final int groupId,                final IFingerprintServiceReceiver receiver) {            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission            final boolean restricted = isRestricted();            // Group ID is arbitrarily set to parent profile user ID. It just represents            // the default fingerprints for the user.            final int effectiveGroupId = getEffectiveUserId(groupId);            mHandler.post(new Runnable() {                @Override                public void run() {                    startRemove(token, fingerId, effectiveGroupId, receiver, restricted);                }            });        }        @Override // Binder call        public boolean isHardwareDetected(long deviceId, String opPackageName) {            if (!canUseFingerprint(opPackageName)) {                return false;            }            return mHalDeviceId != 0;        }        @Override // Binder call        public void rename(final int fingerId, final int groupId, final String name) {            checkPermission(MANAGE_FINGERPRINT);            // Group ID is arbitrarily set to parent profile user ID. It just represents            // the default fingerprints for the user.            final int effectiveGroupId = getEffectiveUserId(groupId);            mHandler.post(new Runnable() {                @Override                public void run() {                    mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,                            effectiveGroupId, name);                }            });        }        @Override // Binder call        public List getEnrolledFingerprints(int userId, String opPackageName) {            if (!canUseFingerprint(opPackageName)) {                return Collections.emptyList();            }            int effectiveUserId = getEffectiveUserId(userId);            return FingerprintService.this.getEnrolledFingerprints(effectiveUserId);        }        @Override // Binder call        public boolean hasEnrolledFingerprints(int userId, String opPackageName) {            if (!canUseFingerprint(opPackageName)) {                return false;            }            int effectiveUserId  = getEffectiveUserId(userId);            return FingerprintService.this.hasEnrolledFingerprints(effectiveUserId);        }        @Override // Binder call        public long getAuthenticatorId(String opPackageName) {            // In this method, we're not checking whether the caller is permitted to use fingerprint            // API because current authenticator ID is leaked (in a more contrived way) via Android            // Keystore (android.security.keystore package): the user of that API can create a key            // which requires fingerprint authentication for its use, and then query the key's            // characteristics (hidden API) which returns, among other things, fingerprint            // authenticator ID which was active at key creation time.            //            // Reason: The part of Android Keystore which runs inside an app's process invokes this            // method in certain cases. Those cases are not always where the developer demonstrates            // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an            // unexpected SecurityException this method does not check whether its caller is            // permitted to use fingerprint API.            //            // The permission check should be restored once Android Keystore no longer invokes this            // method from inside app processes.            return FingerprintService.this.getAuthenticatorId();        }    }    @Override    public void onStart() {        publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());        IFingerprintDaemon daemon = getFingerprintDaemon();        if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);        listenForUserSwitches();    }    private void updateActiveGroup(int userId) {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon != null) {            try {                userId = getEffectiveUserId(userId);                final File systemDir = Environment.getUserSystemDirectory(userId);                final File fpDir = new File(systemDir, FP_DATA_DIR);                if (!fpDir.exists()) {                    if (!fpDir.mkdir()) {                        Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath());                        return;                    }                    // Calling mkdir() from this process will create a directory with our                    // permissions (inherited from the containing dir). This command fixes                    // the label.                    if (!SELinux.restorecon(fpDir)) {                        Slog.w(TAG, "Restorecons failed. Directory will have wrong label.");                        return;                    }                }                daemon.setActiveGroup(userId, fpDir.getAbsolutePath().getBytes());            } catch (RemoteException e) {                Slog.e(TAG, "Failed to setActiveGroup():", e);            }        }    }    private void listenForUserSwitches() {        try {            ActivityManagerNative.getDefault().registerUserSwitchObserver(                new IUserSwitchObserver.Stub() {                    @Override                    public void onUserSwitching(int newUserId, IRemoteCallback reply) {                        mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)                                .sendToTarget();                    }                    @Override                    public void onUserSwitchComplete(int newUserId) throws RemoteException {                        // Ignore.                    }                    @Override                    public void onForegroundProfileSwitch(int newProfileId) {                        // Ignore.                    }                });        } catch (RemoteException e) {            Slog.w(TAG, "Failed to listen for user switching event" ,e);        }    }    public long getAuthenticatorId() {        IFingerprintDaemon daemon = getFingerprintDaemon();        if (daemon != null) {            try {                return daemon.getAuthenticatorId();            } catch (RemoteException e) {                Slog.e(TAG, "getAuthenticatorId failed", e);            }        }        return 0;    }}


FingerprintsUserState.java

/* * Copyright (C) 2015 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.content.Context;import android.hardware.fingerprint.Fingerprint;import android.os.AsyncTask;import android.os.Environment;import android.util.AtomicFile;import android.util.Slog;import android.util.Xml;import com.android.internal.annotations.GuardedBy;import libcore.io.IoUtils;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;import org.xmlpull.v1.XmlSerializer;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.ArrayList;import java.util.List;/** * Class managing the set of fingerprint per user across device reboots. */class FingerprintsUserState {    private static final String TAG = "FingerprintState";    private static final String FINGERPRINT_FILE = "settings_fingerprint.xml";    private static final String TAG_FINGERPRINTS = "fingerprints";    private static final String TAG_FINGERPRINT = "fingerprint";    private static final String ATTR_NAME = "name";    private static final String ATTR_GROUP_ID = "groupId";    private static final String ATTR_FINGER_ID = "fingerId";    private static final String ATTR_DEVICE_ID = "deviceId";    private final File mFile;    @GuardedBy("this")    private final ArrayList mFingerprints = new ArrayList();    private final Context mCtx;    public FingerprintsUserState(Context ctx, int userId) {        mFile = getFileForUser(userId);        mCtx = ctx;        synchronized (this) {            readStateSyncLocked();        }    }    public void addFingerprint(int fingerId, int groupId) {        synchronized (this) {            mFingerprints.add(new Fingerprint(getUniqueName(), groupId, fingerId, 0));            scheduleWriteStateLocked();        }    }    public void removeFingerprint(int fingerId) {        synchronized (this) {            for (int i = 0; i < mFingerprints.size(); i++) {                if (mFingerprints.get(i).getFingerId() == fingerId) {                    mFingerprints.remove(i);                    scheduleWriteStateLocked();                    break;                }            }        }    }    public void renameFingerprint(int fingerId, CharSequence name) {        synchronized (this) {            for (int i = 0; i < mFingerprints.size(); i++) {                if (mFingerprints.get(i).getFingerId() == fingerId) {                    Fingerprint old = mFingerprints.get(i);                    mFingerprints.set(i, new Fingerprint(name, old.getGroupId(), old.getFingerId(),                            old.getDeviceId()));                    scheduleWriteStateLocked();                    break;                }            }        }    }    public List getFingerprints() {        synchronized (this) {            return getCopy(mFingerprints);        }    }    /**     * Finds a unique name for the given fingerprint     * @return unique name     */    private String getUniqueName() {        int guess = 1;        while (true) {            // Not the most efficient algorithm in the world, but there shouldn't be more than 10            String name = mCtx.getString(com.android.internal.R.string.fingerprint_name_template,                    guess);            if (isUnique(name)) {                return name;            }            guess++;        }    }    private boolean isUnique(String name) {        for (Fingerprint fp : mFingerprints) {            if (fp.getName().equals(name)) {                return false;            }        }        return true;    }    private static File getFileForUser(int userId) {        return new File(Environment.getUserSystemDirectory(userId), FINGERPRINT_FILE);    }    private final Runnable mWriteStateRunnable = new Runnable() {        @Override        public void run() {            doWriteState();        }    };    private void scheduleWriteStateLocked() {        AsyncTask.execute(mWriteStateRunnable);    }    private ArrayList getCopy(ArrayList array) {        ArrayList result = new ArrayList(array.size());        for (int i = 0; i < array.size(); i++) {            Fingerprint fp = array.get(i);            result.add(new Fingerprint(fp.getName(), fp.getGroupId(), fp.getFingerId(),                    fp.getDeviceId()));        }        return result;    }    private void doWriteState() {        AtomicFile destination = new AtomicFile(mFile);        ArrayList fingerprints;        synchronized (this) {            fingerprints = getCopy(mFingerprints);        }        FileOutputStream out = null;        try {            out = destination.startWrite();            XmlSerializer serializer = Xml.newSerializer();            serializer.setOutput(out, "utf-8");            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);            serializer.startDocument(null, true);            serializer.startTag(null, TAG_FINGERPRINTS);            final int count = fingerprints.size();            for (int i = 0; i < count; i++) {                Fingerprint fp = fingerprints.get(i);                serializer.startTag(null, TAG_FINGERPRINT);                serializer.attribute(null, ATTR_FINGER_ID, Integer.toString(fp.getFingerId()));                serializer.attribute(null, ATTR_NAME, fp.getName().toString());                serializer.attribute(null, ATTR_GROUP_ID, Integer.toString(fp.getGroupId()));                serializer.attribute(null, ATTR_DEVICE_ID, Long.toString(fp.getDeviceId()));                serializer.endTag(null, TAG_FINGERPRINT);            }            serializer.endTag(null, TAG_FINGERPRINTS);            serializer.endDocument();            destination.finishWrite(out);            // Any error while writing is fatal.        } catch (Throwable t) {            Slog.wtf(TAG, "Failed to write settings, restoring backup", t);            destination.failWrite(out);            throw new IllegalStateException("Failed to write fingerprints", t);        } finally {            IoUtils.closeQuietly(out);        }    }    private void readStateSyncLocked() {        FileInputStream in;        if (!mFile.exists()) {            return;        }        try {            in = new FileInputStream(mFile);        } catch (FileNotFoundException fnfe) {            Slog.i(TAG, "No fingerprint state");            return;        }        try {            XmlPullParser parser = Xml.newPullParser();            parser.setInput(in, null);            parseStateLocked(parser);        } catch (XmlPullParserException | IOException e) {            throw new IllegalStateException("Failed parsing settings file: "                    + mFile , e);        } finally {            IoUtils.closeQuietly(in);        }    }    private void parseStateLocked(XmlPullParser parser)            throws IOException, XmlPullParserException {        final int outerDepth = parser.getDepth();        int type;        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {                continue;            }            String tagName = parser.getName();            if (tagName.equals(TAG_FINGERPRINTS)) {                parseFingerprintsLocked(parser);            }        }    }    private void parseFingerprintsLocked(XmlPullParser parser)            throws IOException, XmlPullParserException {        final int outerDepth = parser.getDepth();        int type;        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {                continue;            }            String tagName = parser.getName();            if (tagName.equals(TAG_FINGERPRINT)) {                String name = parser.getAttributeValue(null, ATTR_NAME);                String groupId = parser.getAttributeValue(null, ATTR_GROUP_ID);                String fingerId = parser.getAttributeValue(null, ATTR_FINGER_ID);                String deviceId = parser.getAttributeValue(null, ATTR_DEVICE_ID);                mFingerprints.add(new Fingerprint(name, Integer.parseInt(groupId),                        Integer.parseInt(fingerId), Integer.parseInt(deviceId)));            }        }    }}


FingerprintUtils.java

/** * Copyright (C) 2015 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.content.Context;import android.hardware.fingerprint.Fingerprint;import android.os.Vibrator;import android.util.SparseArray;import com.android.internal.annotations.GuardedBy;import java.util.List;/** * Utility class for dealing with fingerprints and fingerprint settings. */public class FingerprintUtils {    private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};    private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};    private static final Object sInstanceLock = new Object();    private static FingerprintUtils sInstance;    @GuardedBy("this")    private final SparseArray mUsers = new SparseArray<>();    public static FingerprintUtils getInstance() {        synchronized (sInstanceLock) {            if (sInstance == null) {                sInstance = new FingerprintUtils();            }        }        return sInstance;    }    private FingerprintUtils() {    }    public List getFingerprintsForUser(Context ctx, int userId) {        return getStateForUser(ctx, userId).getFingerprints();    }    public void addFingerprintForUser(Context ctx, int fingerId, int userId) {        getStateForUser(ctx, userId).addFingerprint(fingerId, userId);    }    public void removeFingerprintIdForUser(Context ctx, int fingerId, int userId) {        getStateForUser(ctx, userId).removeFingerprint(fingerId);    }    public void renameFingerprintForUser(Context ctx, int fingerId, int userId, CharSequence name) {        getStateForUser(ctx, userId).renameFingerprint(fingerId, name);    }    public static void vibrateFingerprintError(Context context) {        Vibrator vibrator = context.getSystemService(Vibrator.class);        if (vibrator != null) {            vibrator.vibrate(FP_ERROR_VIBRATE_PATTERN, -1);        }    }    public static void vibrateFingerprintSuccess(Context context) {        Vibrator vibrator = context.getSystemService(Vibrator.class);        if (vibrator != null) {            vibrator.vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);        }    }    private FingerprintsUserState getStateForUser(Context ctx, int userId) {        synchronized (this) {            FingerprintsUserState state = mUsers.get(userId);            if (state == null) {                state = new FingerprintsUserState(ctx, userId);                mUsers.put(userId, state);            }            return state;        }    }}



/frameworks/base/core/java/android/hardware/fingerprint/

-------------------------------------------------------------------------------------------

Fingerprint.aidl

/* * Copyright (C) 2015 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.hardware.fingerprint;// @hideparcelable Fingerprint;


Fingerprint.java

/* * Copyright (C) 2015 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.hardware.fingerprint;import android.os.Parcel;import android.os.Parcelable;/** * Container for fingerprint metadata. * @hide */public final class Fingerprint implements Parcelable {    private CharSequence mName;    private int mGroupId;    private int mFingerId;    private long mDeviceId; // physical device this is associated with    public Fingerprint(CharSequence name, int groupId, int fingerId, long deviceId) {        mName = name;        mGroupId = groupId;        mFingerId = fingerId;        mDeviceId = deviceId;    }    private Fingerprint(Parcel in) {        mName = in.readString();        mGroupId = in.readInt();        mFingerId = in.readInt();        mDeviceId = in.readLong();    }    /**     * Gets the human-readable name for the given fingerprint.     * @return name given to finger     */    public CharSequence getName() { return mName; }    /**     * Gets the device-specific finger id.  Used by Settings to map a name to a specific     * fingerprint template.     * @return device-specific id for this finger     * @hide     */    public int getFingerId() { return mFingerId; }    /**     * Gets the group id specified when the fingerprint was enrolled.     * @return group id for the set of fingerprints this one belongs to.     * @hide     */    public int getGroupId() { return mGroupId; }    /**     * Device this fingerprint belongs to.     * @hide     */    public long getDeviceId() { return mDeviceId; }    public int describeContents() {        return 0;    }    public void writeToParcel(Parcel out, int flags) {        out.writeString(mName.toString());        out.writeInt(mGroupId);        out.writeInt(mFingerId);        out.writeLong(mDeviceId);    }    public static final Parcelable.Creator CREATOR            = new Parcelable.Creator() {        public Fingerprint createFromParcel(Parcel in) {            return new Fingerprint(in);        }        public Fingerprint[] newArray(int size) {            return new Fingerprint[size];        }    };};


FingerprintManager.java

/** * 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.hardware.fingerprint;import android.annotation.NonNull;import android.annotation.Nullable;import android.annotation.RequiresPermission;import android.app.ActivityManagerNative;import android.content.Context;import android.os.Binder;import android.os.CancellationSignal;import android.os.CancellationSignal.OnCancelListener;import android.os.Handler;import android.os.IBinder;import android.os.Looper;import android.os.RemoteException;import android.os.UserHandle;import android.security.keystore.AndroidKeyStoreProvider;import android.util.Log;import android.util.Slog;import java.security.Signature;import java.util.List;import javax.crypto.Cipher;import javax.crypto.Mac;import static android.Manifest.permission.USE_FINGERPRINT;import static android.Manifest.permission.MANAGE_FINGERPRINT;/** * A class that coordinates access to the fingerprint hardware. * 

* Use {@link android.content.Context#getSystemService(java.lang.String)} * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get * an instance of this class. */public class FingerprintManager { private static final String TAG = "FingerprintManager"; private static final boolean DEBUG = true; private static final int MSG_ENROLL_RESULT = 100; private static final int MSG_ACQUIRED = 101; private static final int MSG_AUTHENTICATION_SUCCEEDED = 102; private static final int MSG_AUTHENTICATION_FAILED = 103; private static final int MSG_ERROR = 104; private static final int MSG_REMOVED = 105; // // Error messages from fingerprint hardware during initilization, enrollment, authentication or // removal. Must agree with the list in fingerprint.h // /** * The hardware is unavailable. Try again later. */ public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; /** * Error state returned when the sensor was unable to process the current image. */ public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; /** * Error state returned when the current request has been running too long. This is intended to * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is * platform and sensor-specific, but is generally on the order of 30 seconds. */ public static final int FINGERPRINT_ERROR_TIMEOUT = 3; /** * Error state returned for operations like enrollment; the operation cannot be completed * because there's not enough storage remaining to complete the operation. */ public static final int FINGERPRINT_ERROR_NO_SPACE = 4; /** * The operation was canceled because the fingerprint sensor is unavailable. For example, * this may happen when the user is switched, the device is locked or another pending operation * prevents or disables it. */ public static final int FINGERPRINT_ERROR_CANCELED = 5; /** * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically * this will happen when the provided fingerprint id was incorrect. * * @hide */ public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6; /** * The operation was canceled because the API is locked out due to too many attempts. */ public static final int FINGERPRINT_ERROR_LOCKOUT = 7; /** * Hardware vendors may extend this list if there are conditions that do not fall under one of * the above categories. Vendors are responsible for providing error strings for these errors. * @hide */ public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; // // Image acquisition messages. Must agree with those in fingerprint.h // /** * The image acquired was good. */ public static final int FINGERPRINT_ACQUIRED_GOOD = 0; /** * Only a partial fingerprint image was detected. During enrollment, the user should be * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor." */ public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; /** * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}). */ public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; /** * The fingerprint image was too noisy due to suspected or detected dirt on the sensor. * For example, it's reasonable return this after multiple * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor * when this is returned. */ public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; /** * The fingerprint image was unreadable due to lack of motion. This is most appropriate for * linear array sensors that require a swipe motion. */ public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; /** * The fingerprint image was incomplete due to quick motion. While mostly appropriate for * linear array sensors, this could also happen if the finger was moved during acquisition. * The user should be asked to move the finger slower (linear) or leave the finger on the sensor * longer. */ public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; /** * Hardware vendors may extend this list if there are conditions that do not fall under one of * the above categories. Vendors are responsible for providing error strings for these errors. * @hide */ public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; private IFingerprintService mService; private Context mContext; private IBinder mToken = new Binder(); private AuthenticationCallback mAuthenticationCallback; private EnrollmentCallback mEnrollmentCallback; private RemovalCallback mRemovalCallback; private CryptoObject mCryptoObject; private Fingerprint mRemovalFingerprint; private Handler mHandler; private class OnEnrollCancelListener implements OnCancelListener { @Override public void onCancel() { cancelEnrollment(); } } private class OnAuthenticationCancelListener implements OnCancelListener { private CryptoObject mCrypto; public OnAuthenticationCancelListener(CryptoObject crypto) { mCrypto = crypto; } @Override public void onCancel() { cancelAuthentication(mCrypto); } } /** * A wrapper class for the crypto objects supported by FingerprintManager. Currently the * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. */ public static final class CryptoObject { public CryptoObject(@NonNull Signature signature) { mCrypto = signature; } public CryptoObject(@NonNull Cipher cipher) { mCrypto = cipher; } public CryptoObject(@NonNull Mac mac) { mCrypto = mac; } /** * Get {@link Signature} object. * @return {@link Signature} object or null if this doesn't contain one. */ public Signature getSignature() { return mCrypto instanceof Signature ? (Signature) mCrypto : null; } /** * Get {@link Cipher} object. * @return {@link Cipher} object or null if this doesn't contain one. */ public Cipher getCipher() { return mCrypto instanceof Cipher ? (Cipher) mCrypto : null; } /** * Get {@link Mac} object. * @return {@link Mac} object or null if this doesn't contain one. */ public Mac getMac() { return mCrypto instanceof Mac ? (Mac) mCrypto : null; } /** * @hide * @return the opId associated with this object or 0 if none */ public long getOpId() { return mCrypto != null ? AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0; } private final Object mCrypto; }; /** * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject, * CancellationSignal, int, AuthenticationCallback, Handler)}. */ public static class AuthenticationResult { private Fingerprint mFingerprint; private CryptoObject mCryptoObject; /** * Authentication result * * @param crypto the crypto object * @param fingerprint the recognized fingerprint data, if allowed. * @hide */ public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) { mCryptoObject = crypto; mFingerprint = fingerprint; } /** * Obtain the crypto object associated with this transaction * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject, * CancellationSignal, int, AuthenticationCallback, Handler)}. */ public CryptoObject getCryptoObject() { return mCryptoObject; } /** * Obtain the Fingerprint associated with this operation. Applications are strongly * discouraged from associating specific fingers with specific applications or operations. * * @hide */ public Fingerprint getFingerprint() { return mFingerprint; } }; /** * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject, * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link * FingerprintManager#authenticate(CryptoObject, CancellationSignal, * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to * fingerprint events. */ public static abstract class AuthenticationCallback { /** * Called when an unrecoverable error has been encountered and the operation is complete. * No further callbacks will be made on this object. * @param errorCode An integer identifying the error message * @param errString A human-readable error string that can be shown in UI */ public void onAuthenticationError(int errorCode, CharSequence errString) { } /** * Called when a recoverable error has been encountered during authentication. The help * string is provided to give the user guidance for what went wrong, such as * "Sensor dirty, please clean it." * @param helpCode An integer identifying the error message * @param helpString A human-readable string that can be shown in UI */ public void onAuthenticationHelp(int helpCode, CharSequence helpString) { } /** * Called when a fingerprint is recognized. * @param result An object containing authentication-related data */ public void onAuthenticationSucceeded(AuthenticationResult result) { } /** * Called when a fingerprint is valid but not recognized. */ public void onAuthenticationFailed() { } /** * Called when a fingerprint image has been acquired, but wasn't processed yet. * * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants * @hide */ public void onAuthenticationAcquired(int acquireInfo) {} }; /** * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback, * CancellationSignal, int). Users of {@link #FingerprintManager()} * must provide an implementation of this to {@link FingerprintManager#enroll(long, * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events. * * @hide */ public static abstract class EnrollmentCallback { /** * Called when an unrecoverable error has been encountered and the operation is complete. * No further callbacks will be made on this object. * @param errMsgId An integer identifying the error message * @param errString A human-readable error string that can be shown in UI */ public void onEnrollmentError(int errMsgId, CharSequence errString) { } /** * Called when a recoverable error has been encountered during enrollment. The help * string is provided to give the user guidance for what went wrong, such as * "Sensor dirty, please clean it" or what they need to do next, such as * "Touch sensor again." * @param helpMsgId An integer identifying the error message * @param helpString A human-readable string that can be shown in UI */ public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { } /** * Called as each enrollment step progresses. Enrollment is considered complete when * remaining reaches 0. This function will not be called if enrollment fails. See * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} * @param remaining The number of remaining steps */ public void onEnrollmentProgress(int remaining) { } }; /** * Callback structure provided to {@link FingerprintManager#remove(int). Users of * {@link #FingerprintManager()} may optionally provide an implementation of this to * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to * fingerprint template removal events. * * @hide */ public static abstract class RemovalCallback { /** * Called when the given fingerprint can't be removed. * @param fp The fingerprint that the call attempted to remove * @param errMsgId An associated error message id * @param errString An error message indicating why the fingerprint id can't be removed */ public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { } /** * Called when a given fingerprint is successfully removed. * @param fingerprint the fingerprint template that was removed. */ public void onRemovalSucceeded(Fingerprint fingerprint) { } }; /** * Request authentication of a crypto object. This call warms up the fingerprint hardware * and starts scanning for a fingerprint. It terminates when * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at * which point the object is no longer valid. The operation can be canceled by using the * provided cancel object. * * @param crypto object associated with the call or null if none required. * @param cancel an object that can be used to cancel authentication * @param flags optional flags; should be 0 * @param callback an object to receive authentication events * @param handler an optional handler to handle callback events * * @throws IllegalArgumentException if the crypto operation is not supported or is not backed * by Android Keystore * facility. * @throws IllegalStateException if the crypto primitive is not initialized. */ @RequiresPermission(USE_FINGERPRINT) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) { authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId()); } /** * Use the provided handler thread for events. * @param handler */ private void useHandler(Handler handler) { if (handler != null) { mHandler = new MyHandler(handler.getLooper()); } else if (mHandler.getLooper() != mContext.getMainLooper()){ mHandler = new MyHandler(mContext.getMainLooper()); } } /** * Per-user version * @hide */ @RequiresPermission(USE_FINGERPRINT) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) { if (callback == null) { throw new IllegalArgumentException("Must supply an authentication callback"); } if (cancel != null) { if (cancel.isCanceled()) { Log.w(TAG, "authentication already canceled"); return; } else { cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto)); } } if (mService != null) try { useHandler(handler); mAuthenticationCallback = callback; mCryptoObject = crypto; long sessionId = crypto != null ? crypto.getOpId() : 0; mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags, mContext.getOpPackageName()); } catch (RemoteException e) { Log.w(TAG, "Remote exception while authenticating: ", e); if (callback != null) { // Though this may not be a hardware issue, it will cause apps to give up or try // again later. callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE, getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); } } } /** * Request fingerprint enrollment. This call warms up the fingerprint hardware * and starts scanning for fingerprints. Progress will be indicated by callbacks to the * {@link EnrollmentCallback} object. It terminates when * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at * which point the object is no longer valid. The operation can be canceled by using the * provided cancel object. * @param token a unique token provided by a recent creation or verification of device * credentials (e.g. pin, pattern or password). * @param cancel an object that can be used to cancel enrollment * @param flags optional flags * @param callback an object to receive enrollment events * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) public void enroll(byte [] token, CancellationSignal cancel, int flags, EnrollmentCallback callback) { if (callback == null) { throw new IllegalArgumentException("Must supply an enrollment callback"); } if (cancel != null) { if (cancel.isCanceled()) { Log.w(TAG, "enrollment already canceled"); return; } else { cancel.setOnCancelListener(new OnEnrollCancelListener()); } } if (mService != null) try { mEnrollmentCallback = callback; mService.enroll(mToken, token, getCurrentUserId(), mServiceReceiver, flags); } catch (RemoteException e) { Log.w(TAG, "Remote exception in enroll: ", e); if (callback != null) { // Though this may not be a hardware issue, it will cause apps to give up or try // again later. callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE, getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); } } } /** * Requests a pre-enrollment auth token to tie enrollment to the confirmation of * existing device credentials (e.g. pin/pattern/password). * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) public long preEnroll() { long result = 0; if (mService != null) try { result = mService.preEnroll(mToken); } catch (RemoteException e) { Log.w(TAG, "Remote exception in enroll: ", e); } return result; } /** * Finishes enrollment and cancels the current auth token. * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) public int postEnroll() { int result = 0; if (mService != null) try { result = mService.postEnroll(mToken); } catch (RemoteException e) { Log.w(TAG, "Remote exception in post enroll: ", e); } return result; } /** * Remove given fingerprint template from fingerprint hardware and/or protected storage. * @param fp the fingerprint item to remove * @param callback an optional callback to verify that fingerprint templates have been * successfully removed. May be null of no callback is required. * * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) public void remove(Fingerprint fp, RemovalCallback callback) { if (mService != null) try { mRemovalCallback = callback; mRemovalFingerprint = fp; mService.remove(mToken, fp.getFingerId(), getCurrentUserId(), mServiceReceiver); } catch (RemoteException e) { Log.w(TAG, "Remote exception in remove: ", e); if (callback != null) { callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE, getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); } } } /** * Renames the given fingerprint template * @param fpId the fingerprint id * @param newName the new name * * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) public void rename(int fpId, String newName) { // Renames the given fpId if (mService != null) { try { mService.rename(fpId, getCurrentUserId(), newName); } catch (RemoteException e) { Log.v(TAG, "Remote exception in rename(): ", e); } } else { Log.w(TAG, "rename(): Service not connected!"); } } /** * Obtain the list of enrolled fingerprints templates. * @return list of current fingerprint items * * @hide */ @RequiresPermission(USE_FINGERPRINT) public List getEnrolledFingerprints(int userId) { if (mService != null) try { return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); } return null; } /** * Obtain the list of enrolled fingerprints templates. * @return list of current fingerprint items * * @hide */ @RequiresPermission(USE_FINGERPRINT) public List getEnrolledFingerprints() { return getEnrolledFingerprints(UserHandle.myUserId()); } /** * Determine if there is at least one fingerprint enrolled. * * @return true if at least one fingerprint is enrolled, false otherwise */ @RequiresPermission(USE_FINGERPRINT) public boolean hasEnrolledFingerprints() { if (mService != null) try { return mService.hasEnrolledFingerprints(UserHandle.myUserId(), mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); } return false; } /** * Determine if fingerprint hardware is present and functional. * * @return true if hardware is present and functional, false otherwise. */ @RequiresPermission(USE_FINGERPRINT) public boolean isHardwareDetected() { if (mService != null) { try { long deviceId = 0; /* TODO: plumb hardware id to FPMS */ return mService.isHardwareDetected(deviceId, mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e); } } else { Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); } return false; } /** * Retrieves the authenticator token for binding keys to the lifecycle * of the current set of fingerprints. Used only by internal clients. * * @hide */ public long getAuthenticatorId() { if (mService != null) { try { return mService.getAuthenticatorId(mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e); } } else { Log.w(TAG, "getAuthenticatorId(): Service not connected!"); } return 0; } private class MyHandler extends Handler { private MyHandler(Context context) { super(context.getMainLooper()); } private MyHandler(Looper looper) { super(looper); } public void handleMessage(android.os.Message msg) { switch(msg.what) { case MSG_ENROLL_RESULT: sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */); break; case MSG_ACQUIRED: sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */); break; case MSG_AUTHENTICATION_SUCCEEDED: sendAuthenticatedSucceeded((Fingerprint) msg.obj); break; case MSG_AUTHENTICATION_FAILED: sendAuthenticatedFailed(); break; case MSG_ERROR: sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */); break; case MSG_REMOVED: sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */, msg.arg2 /* groupId */); } } private void sendRemovedResult(long deviceId, int fingerId, int groupId) { if (mRemovalCallback != null) { int reqFingerId = mRemovalFingerprint.getFingerId(); int reqGroupId = mRemovalFingerprint.getGroupId(); if (fingerId != reqFingerId) { Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId); } if (fingerId != reqFingerId) { Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId); } mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint); } } private void sendErrorResult(long deviceId, int errMsgId) { if (mEnrollmentCallback != null) { mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId)); } else if (mAuthenticationCallback != null) { mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId)); } else if (mRemovalCallback != null) { mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId, getErrorString(errMsgId)); } } private void sendEnrollResult(Fingerprint fp, int remaining) { if (mEnrollmentCallback != null) { mEnrollmentCallback.onEnrollmentProgress(remaining); } } private void sendAuthenticatedSucceeded(Fingerprint fp) { if (mAuthenticationCallback != null) { final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); mAuthenticationCallback.onAuthenticationSucceeded(result); } } private void sendAuthenticatedFailed() { if (mAuthenticationCallback != null) { mAuthenticationCallback.onAuthenticationFailed(); } } private void sendAcquiredResult(long deviceId, int acquireInfo) { if (mAuthenticationCallback != null) { mAuthenticationCallback.onAuthenticationAcquired(acquireInfo); } final String msg = getAcquiredString(acquireInfo); if (msg == null) { return; } if (mEnrollmentCallback != null) { mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg); } else if (mAuthenticationCallback != null) { mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg); } } }; /** * @hide */ public FingerprintManager(Context context, IFingerprintService service) { mContext = context; mService = service; if (mService == null) { Slog.v(TAG, "FingerprintManagerService was null"); } mHandler = new MyHandler(context); } 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; } } private void cancelEnrollment() { if (mService != null) try { mService.cancelEnrollment(mToken); } catch (RemoteException e) { if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment"); } } private void cancelAuthentication(CryptoObject cryptoObject) { if (mService != null) try { mService.cancelAuthentication(mToken, mContext.getOpPackageName()); } catch (RemoteException e) { if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment"); } } private String getErrorString(int errMsg) { switch (errMsg) { case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: return mContext.getString( com.android.internal.R.string.fingerprint_error_unable_to_process); case FINGERPRINT_ERROR_HW_UNAVAILABLE: return mContext.getString( com.android.internal.R.string.fingerprint_error_hw_not_available); case FINGERPRINT_ERROR_NO_SPACE: return mContext.getString( com.android.internal.R.string.fingerprint_error_no_space); case FINGERPRINT_ERROR_TIMEOUT: return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout); case FINGERPRINT_ERROR_CANCELED: return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled); case FINGERPRINT_ERROR_LOCKOUT: return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout); default: if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) { int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE; String[] msgArray = mContext.getResources().getStringArray( com.android.internal.R.array.fingerprint_error_vendor); if (msgNumber < msgArray.length) { return msgArray[msgNumber]; } } return null; } } private String getAcquiredString(int acquireInfo) { switch (acquireInfo) { case FINGERPRINT_ACQUIRED_GOOD: return null; case FINGERPRINT_ACQUIRED_PARTIAL: return mContext.getString( com.android.internal.R.string.fingerprint_acquired_partial); case FINGERPRINT_ACQUIRED_INSUFFICIENT: return mContext.getString( com.android.internal.R.string.fingerprint_acquired_insufficient); case FINGERPRINT_ACQUIRED_IMAGER_DIRTY: return mContext.getString( com.android.internal.R.string.fingerprint_acquired_imager_dirty); case FINGERPRINT_ACQUIRED_TOO_SLOW: return mContext.getString( com.android.internal.R.string.fingerprint_acquired_too_slow); case FINGERPRINT_ACQUIRED_TOO_FAST: return mContext.getString( com.android.internal.R.string.fingerprint_acquired_too_fast); default: if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) { int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE; String[] msgArray = mContext.getResources().getStringArray( com.android.internal.R.array.fingerprint_acquired_vendor); if (msgNumber < msgArray.length) { return msgArray[msgNumber]; } } return null; } } private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() { @Override // binder call public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget(); } @Override // binder call public void onAcquired(long deviceId, int acquireInfo) { mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget(); } @Override // binder call public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) { mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget(); } @Override // binder call public void onAuthenticationFailed(long deviceId) { mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();; } @Override // binder call public void onError(long deviceId, int error) { mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget(); } @Override // binder call public void onRemoved(long deviceId, int fingerId, int groupId) { mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget(); } };}



IFingerprintDaemon.aidl

/* * Copyright (C) 2015 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.hardware.fingerprint;import android.hardware.fingerprint.IFingerprintDaemonCallback;/** * Communication channel from FingerprintService to FingerprintDaemon (fingerprintd) * @hide */interface IFingerprintDaemon {    int authenticate(long sessionId, int groupId);    int cancelAuthentication();    int enroll(in byte [] token, int groupId, int timeout);    int cancelEnrollment();    long preEnroll();    int remove(int fingerId, int groupId);    long getAuthenticatorId();    int setActiveGroup(int groupId, in byte[] path);    long openHal();    int closeHal();    void init(IFingerprintDaemonCallback callback);    int postEnroll();}


IFingerprintDaemonCallback.aidl

/* * 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.hardware.fingerprint;/** * Communication channel from the fingerprintd back to FingerprintService. * @hide */ interface IFingerprintDaemonCallback {    void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);    void onAcquired(long deviceId, int acquiredInfo);    void onAuthenticated(long deviceId, int fingerId, int groupId);    void onError(long deviceId, int error);    void onRemoved(long deviceId, int fingerId, int groupId);    void onEnumerate(long deviceId, in int [] fingerIds, in int [] groupIds);}


IFingerprintService.aidl

/* * 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.hardware.fingerprint;import android.os.Bundle;import android.hardware.fingerprint.IFingerprintServiceReceiver;import android.hardware.fingerprint.Fingerprint;import java.util.List;/** * Communication channel from client to the fingerprint service. * @hide */interface IFingerprintService {    // Authenticate the given sessionId with a fingerprint    void authenticate(IBinder token, long sessionId, int userId,            IFingerprintServiceReceiver receiver, int flags, String opPackageName);    // Cancel authentication for the given sessionId    void cancelAuthentication(IBinder token, String opPackageName);    // Start fingerprint enrollment    void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver,            int flags);    // Cancel enrollment in progress    void cancelEnrollment(IBinder token);    // Any errors resulting from this call will be returned to the listener    void remove(IBinder token, int fingerId, int groupId, IFingerprintServiceReceiver receiver);    // Rename the fingerprint specified by fingerId and groupId to the given name    void rename(int fingerId, int groupId, String name);    // Get a list of enrolled fingerprints in the given group.    List getEnrolledFingerprints(int groupId, String opPackageName);    // Determine if HAL is loaded and ready    boolean isHardwareDetected(long deviceId, String opPackageName);    // Get a pre-enrollment authentication token    long preEnroll(IBinder token);    // Finish an enrollment sequence and invalidate the authentication token    int postEnroll(IBinder token);    // Determine if a user has at least one enrolled fingerprint    boolean hasEnrolledFingerprints(int groupId, String opPackageName);    // Gets the number of hardware devices    // int getHardwareDeviceCount();    // Gets the unique device id for hardware enumerated at i    // long getHardwareDevice(int i);    // Gets the authenticator ID for fingerprint    long getAuthenticatorId(String opPackageName);}


IFingerprintServiceReceiver.aidl

/* * 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.hardware.fingerprint;import android.hardware.fingerprint.Fingerprint;import android.os.Bundle;import android.os.UserHandle;/** * Communication channel from the FingerprintService back to FingerprintManager. * @hide */oneway interface IFingerprintServiceReceiver {    void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);    void onAcquired(long deviceId, int acquiredInfo);    void onAuthenticationSucceeded(long deviceId, in Fingerprint fp);    void onAuthenticationFailed(long deviceId);    void onError(long deviceId, int error);    void onRemoved(long deviceId, int fingerId, int groupId);}



/system/core/fingerprintd/

-------------------------------------------------------------------------------------------

Android.mk

## Copyright (C) 2015 The Android Open Source Project## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at##      http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.#LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)#LOCAL_MULTILIB :=32 #test bruce LOCAL_CFLAGS := -Wall -Wextra -Werror -WunusedLOCAL_SRC_FILES := \FingerprintDaemonProxy.cpp \IFingerprintDaemon.cpp \IFingerprintDaemonCallback.cpp \fingerprintd.cppLOCAL_MODULE := fingerprintdLOCAL_SHARED_LIBRARIES := \libbinder \liblog \libhardware \libutils \libkeystore_binderinclude $(BUILD_EXECUTABLE)


fingerprintd.cpp

/* * Copyright (C) 2015 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 "fingerprintd"#include #include #include #include #include #include #include #include  // for error codes#include #include #include #include "FingerprintDaemonProxy.h"int main() {    ALOGI("Starting " LOG_TAG);    android::sp serviceManager = android::defaultServiceManager();    android::sp proxy =            android::FingerprintDaemonProxy::getInstance();    android::status_t ret = serviceManager->addService(            android::FingerprintDaemonProxy::descriptor, proxy);    if (ret != android::OK) {        ALOGE("Couldn't register " LOG_TAG " binder service!");        return -1;    }    /*     * We're the only thread in existence, so we're just going to process     * Binder transaction as a single-threaded program.     */    android::IPCThreadState::self()->joinThreadPool();    ALOGI("Done");    return 0;}


FingerprintDaemonProxy.cpp

/* * Copyright (C) 2015 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 "fingerprintd"#include #include #include #include #include #include  // for error codes#include #include "FingerprintDaemonProxy.h"#include #include #include namespace android {FingerprintDaemonProxy* FingerprintDaemonProxy::sInstance = NULL;// Supported fingerprint HAL versionstatic const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 0);FingerprintDaemonProxy::FingerprintDaemonProxy() : mModule(NULL), mDevice(NULL), mCallback(NULL) {}FingerprintDaemonProxy::~FingerprintDaemonProxy() {    closeHal();}void FingerprintDaemonProxy::hal_notify_callback(const fingerprint_msg_t *msg) {    FingerprintDaemonProxy* instance = FingerprintDaemonProxy::getInstance();    const sp callback = instance->mCallback;    if (callback == NULL) {        ALOGE("Invalid callback object");        return;    }    const int64_t device = (int64_t) instance->mDevice;    switch (msg->type) {        case FINGERPRINT_ERROR:            ALOGD("onError(%d)", msg->data.error);            callback->onError(device, msg->data.error);            break;        case FINGERPRINT_ACQUIRED:            ALOGD("onAcquired(%d)", msg->data.acquired.acquired_info);            callback->onAcquired(device, msg->data.acquired.acquired_info);            break;        case FINGERPRINT_AUTHENTICATED:            ALOGD("onAuthenticated(fid=%d, gid=%d)",                    msg->data.authenticated.finger.fid,                    msg->data.authenticated.finger.gid);            if (msg->data.authenticated.finger.fid != 0) {                const uint8_t* hat = reinterpret_cast(&msg->data.authenticated.hat);                instance->notifyKeystore(hat, sizeof(msg->data.authenticated.hat));            }            callback->onAuthenticated(device,                    msg->data.authenticated.finger.fid,                    msg->data.authenticated.finger.gid);            break;        case FINGERPRINT_TEMPLATE_ENROLLING:            ALOGD("onEnrollResult(fid=%d, gid=%d, rem=%d)",                    msg->data.enroll.finger.fid,                    msg->data.enroll.finger.gid,                    msg->data.enroll.samples_remaining);            callback->onEnrollResult(device,                    msg->data.enroll.finger.fid,                    msg->data.enroll.finger.gid,                    msg->data.enroll.samples_remaining);            break;        case FINGERPRINT_TEMPLATE_REMOVED:            ALOGD("onRemove(fid=%d, gid=%d)",                    msg->data.removed.finger.fid,                    msg->data.removed.finger.gid);            callback->onRemoved(device,                    msg->data.removed.finger.fid,                    msg->data.removed.finger.gid);            break;        default:            ALOGE("invalid msg type: %d", msg->type);            return;    }}void FingerprintDaemonProxy::notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length) {    if (auth_token != NULL && auth_token_length > 0) {        // TODO: cache service?        sp < IServiceManager > sm = defaultServiceManager();        sp < IBinder > binder = sm->getService(String16("android.security.keystore"));        sp < IKeystoreService > service = interface_cast < IKeystoreService > (binder);        if (service != NULL) {            status_t ret = service->addAuthToken(auth_token, auth_token_length);            if (ret != ResponseCode::NO_ERROR) {                ALOGE("Falure sending auth token to KeyStore: %d", ret);            }        } else {            ALOGE("Unable to communicate with KeyStore");        }    }}void FingerprintDaemonProxy::init(const sp& callback) {    if (mCallback != NULL && IInterface::asBinder(callback) != IInterface::asBinder(mCallback)) {        IInterface::asBinder(mCallback)->unlinkToDeath(this);    }    IInterface::asBinder(callback)->linkToDeath(this);    mCallback = callback;}int32_t FingerprintDaemonProxy::enroll(const uint8_t* token, ssize_t tokenSize, int32_t groupId,        int32_t timeout) {    ALOG(LOG_VERBOSE, LOG_TAG, "enroll(gid=%d, timeout=%d)\n", groupId, timeout);    if (tokenSize != sizeof(hw_auth_token_t) ) {        ALOG(LOG_VERBOSE, LOG_TAG, "enroll() : invalid token size %zu\n", tokenSize);        return -1;    }    const hw_auth_token_t* authToken = reinterpret_cast(token);    return mDevice->enroll(mDevice, authToken, groupId, timeout);}uint64_t FingerprintDaemonProxy::preEnroll() {    return mDevice->pre_enroll(mDevice);}int32_t FingerprintDaemonProxy::postEnroll() {    return mDevice->post_enroll(mDevice);}int32_t FingerprintDaemonProxy::stopEnrollment() {    ALOG(LOG_VERBOSE, LOG_TAG, "stopEnrollment()\n");    return mDevice->cancel(mDevice);}int32_t FingerprintDaemonProxy::authenticate(uint64_t sessionId, uint32_t groupId) {    ALOG(LOG_VERBOSE, LOG_TAG, "authenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId);    return mDevice->authenticate(mDevice, sessionId, groupId);}int32_t FingerprintDaemonProxy::stopAuthentication() {    ALOG(LOG_VERBOSE, LOG_TAG, "stopAuthentication()\n");    return mDevice->cancel(mDevice);}int32_t FingerprintDaemonProxy::remove(int32_t fingerId, int32_t groupId) {    ALOG(LOG_VERBOSE, LOG_TAG, "remove(fid=%d, gid=%d)\n", fingerId, groupId);    return mDevice->remove(mDevice, groupId, fingerId);}uint64_t FingerprintDaemonProxy::getAuthenticatorId() {    return mDevice->get_authenticator_id(mDevice);}int32_t FingerprintDaemonProxy::setActiveGroup(int32_t groupId, const uint8_t* path,        ssize_t pathlen) {    if (pathlen >= PATH_MAX || pathlen <= 0) {        ALOGE("Bad path length: %zd", pathlen);        return -1;    }    // Convert to null-terminated string    char path_name[PATH_MAX];    memcpy(path_name, path, pathlen);    path_name[pathlen] = '\0';    ALOG(LOG_VERBOSE, LOG_TAG, "setActiveGroup(%d, %s, %zu)", groupId, path_name, pathlen);    return mDevice->set_active_group(mDevice, groupId, path_name);}//add bruce/*typedef struct vendor_fingerprint{        const char * vendor;        const char * dev_node;        const char * lib_name;}vendor_fingerprint_t;#define VENDOR_LIST_COUNT 2vendor_fingerprint_t vendor_list[VENDOR_LIST_COUNT]={        {"sunwave","/dev/sunwave_fp","sunwave.fingerprint"},        {"mas","/dev/madev0","fingerprint"},//mas.fingerprint};*///end bruceint64_t FingerprintDaemonProxy::openHal() {    ALOG(LOG_VERBOSE, LOG_TAG, "nativeOpenHal()\n");    int err;   //add bruce /*        char *sensorId=NULL;        vendor_fingerprint_t *vendor;        for(int i=0;idev_node,F_OK);                if(res==0){                        sensorId=(char*)vendor->lib_name;                         ALOGE("%s find fingerprint vendor %s",__func__,vendor->vendor);                        break;                }        }            if(sensorId==NULL){                ALOGE("Cant't find fingerprint vendor");                return 0;        }*///end bruce    const hw_module_t *hw_module = NULL;//    if (0 != (err = hw_get_module(sensorId, &hw_module))) {//FINGERPRINT_HARDWARE_MODULE_ID test bruce    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;    }    mModule = reinterpret_cast(hw_module);    if (mModule->common.methods->open == NULL) {        ALOGE("No valid open method");        return 0;    }    hw_device_t *device = NULL;    if (0 != (err = mModule->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    }    mDevice = reinterpret_cast(device);    err = mDevice->set_notify(mDevice, hal_notify_callback);    if (err < 0) {        ALOGE("Failed in call to set_notify(), err=%d", err);        return 0;    }    // Sanity check - remove    if (mDevice->notify != hal_notify_callback) {        ALOGE("NOTIFY not set properly: %p != %p", mDevice->notify, hal_notify_callback);    }    ALOG(LOG_VERBOSE, LOG_TAG, "fingerprint HAL successfully initialized");    return reinterpret_cast(mDevice); // This is just a handle}int32_t FingerprintDaemonProxy::closeHal() {    ALOG(LOG_VERBOSE, LOG_TAG, "nativeCloseHal()\n");    if (mDevice == NULL) {        ALOGE("No valid device");        return -ENOSYS;    }    int err;    if (0 != (err = mDevice->common.close(reinterpret_cast(mDevice)))) {        ALOGE("Can't close fingerprint module, error: %d", err);        return err;    }    mDevice = NULL;    return 0;}void FingerprintDaemonProxy::binderDied(const wp& who) {    ALOGD("binder died");    int err;    if (0 != (err = closeHal())) {        ALOGE("Can't close fingerprint device, error: %d", err);    }    if (IInterface::asBinder(mCallback) == who) {        mCallback = NULL;    }}}


FingerprintDaemonRroxy.h

/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#ifndef FINGERPRINT_DAEMON_PROXY_H_#define FINGERPRINT_DAEMON_PROXY_H_#include "IFingerprintDaemon.h"#include "IFingerprintDaemonCallback.h"namespace android {class FingerprintDaemonProxy : public BnFingerprintDaemon {    public:        static FingerprintDaemonProxy* getInstance() {            if (sInstance == NULL) {                sInstance = new FingerprintDaemonProxy();            }            return sInstance;        }        // These reflect binder methods.        virtual void init(const sp& callback);        virtual int32_t enroll(const uint8_t* token, ssize_t tokenLength, int32_t groupId, int32_t timeout);        virtual uint64_t preEnroll();        virtual int32_t postEnroll();        virtual int32_t stopEnrollment();        virtual int32_t authenticate(uint64_t sessionId, uint32_t groupId);        virtual int32_t stopAuthentication();        virtual int32_t remove(int32_t fingerId, int32_t groupId);        virtual uint64_t getAuthenticatorId();        virtual int32_t setActiveGroup(int32_t groupId, const uint8_t* path, ssize_t pathLen);        virtual int64_t openHal();        virtual int32_t closeHal();    private:        FingerprintDaemonProxy();        virtual ~FingerprintDaemonProxy();        void binderDied(const wp& who);        void notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length);        static void hal_notify_callback(const fingerprint_msg_t *msg);        static FingerprintDaemonProxy* sInstance;        fingerprint_module_t const* mModule;        fingerprint_device_t* mDevice;        sp mCallback;};} // namespace android#endif // FINGERPRINT_DAEMON_PROXY_H_


FingerprintDaemon.cpp

/* * Copyright 2015, 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.*/#include #include #include #include #include #include #include #include  // for error code#include #include #include #include "IFingerprintDaemon.h"#include "IFingerprintDaemonCallback.h"namespace android {static const String16 USE_FINGERPRINT_PERMISSION("android.permission.USE_FINGERPRINT");static const String16 MANAGE_FINGERPRINT_PERMISSION("android.permission.MANAGE_FINGERPRINT");static const String16 HAL_FINGERPRINT_PERMISSION("android.permission.MANAGE_FINGERPRINT"); // TODOstatic const String16 DUMP_PERMISSION("android.permission.DUMP");const android::String16IFingerprintDaemon::descriptor("android.hardware.fingerprint.IFingerprintDaemon");const android::String16&IFingerprintDaemon::getInterfaceDescriptor() const {    return IFingerprintDaemon::descriptor;}status_t BnFingerprintDaemon::onTransact(uint32_t code, const Parcel& data, Parcel* reply,        uint32_t flags) {    switch(code) {        case AUTHENTICATE: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const uint64_t sessionId = data.readInt64();            const uint32_t groupId = data.readInt32();            const int32_t ret = authenticate(sessionId, groupId);            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        };        case CANCEL_AUTHENTICATION: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const int32_t ret = stopAuthentication();            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        }        case ENROLL: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const ssize_t tokenSize = data.readInt32();            const uint8_t* token = static_cast(data.readInplace(tokenSize));            const int32_t groupId = data.readInt32();            const int32_t timeout = data.readInt32();            const int32_t ret = enroll(token, tokenSize, groupId, timeout);            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        }        case CANCEL_ENROLLMENT: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const int32_t ret = stopEnrollment();            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        }        case PRE_ENROLL: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const uint64_t ret = preEnroll();            reply->writeNoException();            reply->writeInt64(ret);            return NO_ERROR;        }        case POST_ENROLL: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const int32_t ret = postEnroll();            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        }        case REMOVE: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const int32_t fingerId = data.readInt32();            const int32_t groupId = data.readInt32();            const int32_t ret = remove(fingerId, groupId);            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        }        case GET_AUTHENTICATOR_ID: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const uint64_t ret = getAuthenticatorId();            reply->writeNoException();            reply->writeInt64(ret);            return NO_ERROR;        }        case SET_ACTIVE_GROUP: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const int32_t group = data.readInt32();            const ssize_t pathSize = data.readInt32();            const uint8_t* path = static_cast(data.readInplace(pathSize));            const int32_t ret = setActiveGroup(group, path, pathSize);            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        }        case OPEN_HAL: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const int64_t ret = openHal();            reply->writeNoException();            reply->writeInt64(ret);            return NO_ERROR;        }        case CLOSE_HAL: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            const int32_t ret = closeHal();            reply->writeNoException();            reply->writeInt32(ret);            return NO_ERROR;        }        case INIT: {            CHECK_INTERFACE(IFingerprintDaemon, data, reply);            if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) {                return PERMISSION_DENIED;            }            sp callback =                    interface_cast(data.readStrongBinder());            init(callback);            reply->writeNoException();            return NO_ERROR;        }        default:            return BBinder::onTransact(code, data, reply, flags);    }};bool BnFingerprintDaemon::checkPermission(const String16& permission) {    const IPCThreadState* ipc = IPCThreadState::self();    const int calling_pid = ipc->getCallingPid();    const int calling_uid = ipc->getCallingUid();    return PermissionCache::checkPermission(permission, calling_pid, calling_uid);}}; // namespace android


IFingerprintDaemon.h

/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#ifndef IFINGERPRINT_DAEMON_H_#define IFINGERPRINT_DAEMON_H_#include #include namespace android {class IFingerprintDaemonCallback;/** Abstract base class for native implementation of FingerprintService.** Note: This must be kept manually in sync with IFingerprintDaemon.aidl*/class IFingerprintDaemon : public IInterface, public IBinder::DeathRecipient {    public:        enum {           AUTHENTICATE = IBinder::FIRST_CALL_TRANSACTION + 0,           CANCEL_AUTHENTICATION = IBinder::FIRST_CALL_TRANSACTION + 1,           ENROLL = IBinder::FIRST_CALL_TRANSACTION + 2,           CANCEL_ENROLLMENT = IBinder::FIRST_CALL_TRANSACTION + 3,           PRE_ENROLL = IBinder::FIRST_CALL_TRANSACTION + 4,           REMOVE = IBinder::FIRST_CALL_TRANSACTION + 5,           GET_AUTHENTICATOR_ID = IBinder::FIRST_CALL_TRANSACTION + 6,           SET_ACTIVE_GROUP = IBinder::FIRST_CALL_TRANSACTION + 7,           OPEN_HAL = IBinder::FIRST_CALL_TRANSACTION + 8,           CLOSE_HAL = IBinder::FIRST_CALL_TRANSACTION + 9,           INIT = IBinder::FIRST_CALL_TRANSACTION + 10,           POST_ENROLL = IBinder::FIRST_CALL_TRANSACTION + 11,        };        IFingerprintDaemon() { }        virtual ~IFingerprintDaemon() { }        virtual const android::String16& getInterfaceDescriptor() const;        // Binder interface methods        virtual void init(const sp& callback) = 0;        virtual int32_t enroll(const uint8_t* token, ssize_t tokenLength, int32_t groupId,                int32_t timeout) = 0;        virtual uint64_t preEnroll() = 0;        virtual int32_t postEnroll() = 0;        virtual int32_t stopEnrollment() = 0;        virtual int32_t authenticate(uint64_t sessionId, uint32_t groupId) = 0;        virtual int32_t stopAuthentication() = 0;        virtual int32_t remove(int32_t fingerId, int32_t groupId) = 0;        virtual uint64_t getAuthenticatorId() = 0;        virtual int32_t setActiveGroup(int32_t groupId, const uint8_t* path, ssize_t pathLen) = 0;        virtual int64_t openHal() = 0;        virtual int32_t closeHal() = 0;        // DECLARE_META_INTERFACE - C++ client interface not needed        static const android::String16 descriptor;        static void hal_notify_callback(const fingerprint_msg_t *msg);};// ----------------------------------------------------------------------------class BnFingerprintDaemon: public BnInterface {    public:       virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,               uint32_t flags = 0);    private:       bool checkPermission(const String16& permission);};} // namespace android#endif // IFINGERPRINT_DAEMON_H_


IFingerprintDaemonCallback.cpp

/* * Copyright (C) 2015 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 "IFingerprintDaemonCallback"#include #include #include #include #include "IFingerprintDaemonCallback.h"namespace android {class BpFingerprintDaemonCallback : public BpInterface{public:    BpFingerprintDaemonCallback(const sp& impl) :            BpInterface(impl) {    }    virtual status_t onEnrollResult(int64_t devId, int32_t fpId, int32_t gpId, int32_t rem) {        Parcel data, reply;        data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor());        data.writeInt64(devId);        data.writeInt32(fpId);        data.writeInt32(gpId);        data.writeInt32(rem);        return remote()->transact(ON_ENROLL_RESULT, data, &reply, IBinder::FLAG_ONEWAY);    }    virtual status_t onAcquired(int64_t devId, int32_t acquiredInfo) {        Parcel data, reply;        data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor());        data.writeInt64(devId);        data.writeInt32(acquiredInfo);        return remote()->transact(ON_ACQUIRED, data, &reply, IBinder::FLAG_ONEWAY);    }    virtual status_t onAuthenticated(int64_t devId, int32_t fpId, int32_t gpId) {        Parcel data, reply;        data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor());        data.writeInt64(devId);        data.writeInt32(fpId);        data.writeInt32(gpId);        return remote()->transact(ON_AUTHENTICATED, data, &reply, IBinder::FLAG_ONEWAY);    }    virtual status_t onError(int64_t devId, int32_t error) {        Parcel data, reply;        data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor());        data.writeInt64(devId);        data.writeInt32(error);        return remote()->transact(ON_ERROR, data, &reply, IBinder::FLAG_ONEWAY);    }    virtual status_t onRemoved(int64_t devId, int32_t fpId, int32_t gpId) {        Parcel data, reply;        data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor());        data.writeInt64(devId);        data.writeInt32(fpId);        data.writeInt32(gpId);        return remote()->transact(ON_REMOVED, data, &reply, IBinder::FLAG_ONEWAY);    }    virtual status_t onEnumerate(int64_t devId, const int32_t* fpIds, const int32_t* gpIds,            int32_t sz) {        Parcel data, reply;        data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor());        data.writeInt64(devId);        data.writeInt32Array(sz, fpIds);        data.writeInt32Array(sz, gpIds);        return remote()->transact(ON_ENUMERATE, data, &reply, IBinder::FLAG_ONEWAY);    }};IMPLEMENT_META_INTERFACE(FingerprintDaemonCallback,        "android.hardware.fingerprint.IFingerprintDaemonCallback");}; // namespace android


IFingerprintDaemonCallback.h

/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#ifndef IFINGERPRINT_DAEMON_CALLBACK_H_#define IFINGERPRINT_DAEMON_CALLBACK_H_#include #include #include #include namespace android {/** Communication channel back to FingerprintService.java*/class IFingerprintDaemonCallback : public IInterface {    public:        // must be kept in sync with IFingerprintService.aidl        enum {            ON_ENROLL_RESULT = IBinder::FIRST_CALL_TRANSACTION + 0,            ON_ACQUIRED = IBinder::FIRST_CALL_TRANSACTION + 1,            ON_AUTHENTICATED = IBinder::FIRST_CALL_TRANSACTION + 2,            ON_ERROR = IBinder::FIRST_CALL_TRANSACTION + 3,            ON_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 4,            ON_ENUMERATE = IBinder::FIRST_CALL_TRANSACTION + 5,        };        virtual status_t onEnrollResult(int64_t devId, int32_t fpId, int32_t gpId, int32_t rem) = 0;        virtual status_t onAcquired(int64_t devId, int32_t acquiredInfo) = 0;        virtual status_t onAuthenticated(int64_t devId, int32_t fingerId, int32_t groupId) = 0;        virtual status_t onError(int64_t devId, int32_t error) = 0;        virtual status_t onRemoved(int64_t devId, int32_t fingerId, int32_t groupId) = 0;        virtual status_t onEnumerate(int64_t devId, const int32_t* fpIds, const int32_t* gpIds,                int32_t sz) = 0;        DECLARE_META_INTERFACE(FingerprintDaemonCallback);};}; // namespace android#endif // IFINGERPRINT_DAEMON_CALLBACK_H_


/hardware/libhardware/include/hardware/fingerprint.h

-------------------------------------------------------------------------------------------

fingerprint.h

/* * 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. */#ifndef ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H#define ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H#include #define FINGERPRINT_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0)#define FINGERPRINT_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0)#define FINGERPRINT_HARDWARE_MODULE_ID "fingerprint"typedef enum fingerprint_msg_type {    FINGERPRINT_ERROR = -1,    FINGERPRINT_ACQUIRED = 1,    FINGERPRINT_TEMPLATE_ENROLLING = 3,    FINGERPRINT_TEMPLATE_REMOVED = 4,    FINGERPRINT_AUTHENTICATED = 5} fingerprint_msg_type_t;/* * Fingerprint errors are meant to tell the framework to terminate the current operation and ask * for the user to correct the situation. These will almost always result in messaging and user * interaction to correct the problem. * * For example, FINGERPRINT_ERROR_CANCELED should follow any acquisition message that results in * a situation where the current operation can't continue without user interaction. For example, * if the sensor is dirty during enrollment and no further enrollment progress can be made, * send FINGERPRINT_ACQUIRED_IMAGER_DIRTY followed by FINGERPRINT_ERROR_CANCELED. */typedef enum fingerprint_error {    FINGERPRINT_ERROR_HW_UNAVAILABLE = 1, /* The hardware has an error that can't be resolved. */    FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2, /* Bad data; operation can't continue */    FINGERPRINT_ERROR_TIMEOUT = 3, /* The operation has timed out waiting for user input. */    FINGERPRINT_ERROR_NO_SPACE = 4, /* No space available to store a template */    FINGERPRINT_ERROR_CANCELED = 5, /* The current operation can't proceed. See above. */    FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6, /* fingerprint with given id can't be removed */    FINGERPRINT_ERROR_VENDOR_BASE = 1000 /* vendor-specific error messages start here */} fingerprint_error_t;/* * Fingerprint acquisition info is meant as feedback for the current operation.  Anything but * FINGERPRINT_ACQUIRED_GOOD will be shown to the user as feedback on how to take action on the * current operation. For example, FINGERPRINT_ACQUIRED_IMAGER_DIRTY can be used to tell the user * to clean the sensor.  If this will cause the current operation to fail, an additional * FINGERPRINT_ERROR_CANCELED can be sent to stop the operation in progress (e.g. enrollment). * In general, these messages will result in a "Try again" message. */typedef enum fingerprint_acquired_info {    FINGERPRINT_ACQUIRED_GOOD = 0,    FINGERPRINT_ACQUIRED_PARTIAL = 1, /* sensor needs more data, i.e. longer swipe. */    FINGERPRINT_ACQUIRED_INSUFFICIENT = 2, /* image doesn't contain enough detail for recognition*/    FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3, /* sensor needs to be cleaned */    FINGERPRINT_ACQUIRED_TOO_SLOW = 4, /* mostly swipe-type sensors; not enough data collected */    FINGERPRINT_ACQUIRED_TOO_FAST = 5, /* for swipe and area sensors; tell user to slow down*/    FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000 /* vendor-specific acquisition messages start here */} fingerprint_acquired_info_t;typedef struct fingerprint_finger_id {    uint32_t gid;    uint32_t fid;} fingerprint_finger_id_t;typedef struct fingerprint_enroll {    fingerprint_finger_id_t finger;    /* samples_remaining goes from N (no data collected, but N scans needed)     * to 0 (no more data is needed to build a template). */    uint32_t samples_remaining;    uint64_t msg; /* Vendor specific message. Used for user guidance */} fingerprint_enroll_t;typedef struct fingerprint_removed {    fingerprint_finger_id_t finger;} fingerprint_removed_t;typedef struct fingerprint_acquired {    fingerprint_acquired_info_t acquired_info; /* information about the image */} fingerprint_acquired_t;typedef struct fingerprint_authenticated {    fingerprint_finger_id_t finger;    hw_auth_token_t hat;} fingerprint_authenticated_t;typedef struct fingerprint_msg {    fingerprint_msg_type_t type;    union {        fingerprint_error_t error;        fingerprint_enroll_t enroll;        fingerprint_removed_t removed;        fingerprint_acquired_t acquired;        fingerprint_authenticated_t authenticated;    } data;} fingerprint_msg_t;/* Callback function type */typedef void (*fingerprint_notify_t)(const fingerprint_msg_t *msg);/* Synchronous operation */typedef struct fingerprint_device {    /**     * Common methods of the fingerprint device. This *must* be the first member     * of fingerprint_device as users of this structure will cast a hw_device_t     * to fingerprint_device pointer in contexts where it's known     * the hw_device_t references a fingerprint_device.     */    struct hw_device_t common;    /*     * Client provided callback function to receive notifications.     * Do not set by hand, use the function above instead.     */    fingerprint_notify_t notify;    /*     * Set notification callback:     * Registers a user function that would receive notifications from the HAL     * The call will block if the HAL state machine is in busy state until HAL     * leaves the busy state.     *     * Function return: 0 if callback function is successfuly registered     *                  or a negative number in case of error, generally from the errno.h set.     */    int (*set_notify)(struct fingerprint_device *dev, fingerprint_notify_t notify);    /*     * Fingerprint pre-enroll enroll request:     * Generates a unique token to upper layers to indicate the start of an enrollment transaction.     * This token will be wrapped by security for verification and passed to enroll() for     * verification before enrollment will be allowed. This is to ensure adding a new fingerprint     * template was preceded by some kind of credential confirmation (e.g. device password).     *     * Function return: 0 if function failed     *                  otherwise, a uint64_t of token     */    uint64_t (*pre_enroll)(struct fingerprint_device *dev);    /*     * Fingerprint enroll request:     * Switches the HAL state machine to collect and store a new fingerprint     * template. Switches back as soon as enroll is complete     * (fingerprint_msg.type == FINGERPRINT_TEMPLATE_ENROLLING &&     *  fingerprint_msg.data.enroll.samples_remaining == 0)     * or after timeout_sec seconds.     * The fingerprint template will be assigned to the group gid. User has a choice     * to supply the gid or set it to 0 in which case a unique group id will be generated.     *     * Function return: 0 if enrollment process can be successfully started     *                  or a negative number in case of error, generally from the errno.h set.     *                  A notify() function may be called indicating the error condition.     */    int (*enroll)(struct fingerprint_device *dev, const hw_auth_token_t *hat,                    uint32_t gid, uint32_t timeout_sec);    /*     * Finishes the enroll operation and invalidates the pre_enroll() generated challenge.     * This will be called at the end of a multi-finger enrollment session to indicate     * that no more fingers will be added.     *     * Function return: 0 if the request is accepted     *                  or a negative number in case of error, generally from the errno.h set.     */    int (*post_enroll)(struct fingerprint_device *dev);    /*     * get_authenticator_id:     * Returns a token associated with the current fingerprint set. This value will     * change whenever a new fingerprint is enrolled, thus creating a new fingerprint     * set.     *     * Function return: current authenticator id or 0 if function failed.     */    uint64_t (*get_authenticator_id)(struct fingerprint_device *dev);    /*     * Cancel pending enroll or authenticate, sending FINGERPRINT_ERROR_CANCELED     * to all running clients. Switches the HAL state machine back to the idle state.     * Unlike enroll_done() doesn't invalidate the pre_enroll() challenge.     *     * Function return: 0 if cancel request is accepted     *                  or a negative number in case of error, generally from the errno.h set.     */    int (*cancel)(struct fingerprint_device *dev);    /*     * Enumerate all the fingerprint templates found in the directory set by     * set_active_group()     * This is a synchronous call. The function takes:     * - A pointer to an array of fingerprint_finger_id_t.     * - The size of the array provided, in fingerprint_finger_id_t elements.     * Max_size is a bi-directional parameter and returns the actual number     * of elements copied to the caller supplied array.     * In the absence of errors the function returns the total number of templates     * in the user directory.     * If the caller has no good guess on the size of the array he should call this     * function witn *max_size == 0 and use the return value for the array allocation.     * The caller of this function has a complete list of the templates when *max_size     * is the same as the function return.     *     * Function return: Total number of fingerprint templates in the current storage directory.     *                  or a negative number in case of error, generally from the errno.h set.     */    int (*enumerate)(struct fingerprint_device *dev, fingerprint_finger_id_t *results,        uint32_t *max_size);    /*     * Fingerprint remove request:     * Deletes a fingerprint template.     * Works only within a path set by set_active_group().     * notify() will be called with details on the template deleted.     * fingerprint_msg.type == FINGERPRINT_TEMPLATE_REMOVED and     * fingerprint_msg.data.removed.id indicating the template id removed.     *     * Function return: 0 if fingerprint template(s) can be successfully deleted     *                  or a negative number in case of error, generally from the errno.h set.     */    int (*remove)(struct fingerprint_device *dev, uint32_t gid, uint32_t fid);    /*     * Restricts the HAL operation to a set of fingerprints belonging to a     * group provided.     * The caller must provide a path to a storage location within the user's     * data directory.     *     * Function return: 0 on success     *                  or a negative number in case of error, generally from the errno.h set.     */    int (*set_active_group)(struct fingerprint_device *dev, uint32_t gid,                            const char *store_path);    /*     * Authenticates an operation identifed by operation_id     *     * Function return: 0 on success     *                  or a negative number in case of error, generally from the errno.h set.     */    int (*authenticate)(struct fingerprint_device *dev, uint64_t operation_id, uint32_t gid);    /* Reserved for backward binary compatibility */    void *reserved[4];} fingerprint_device_t;typedef struct fingerprint_module {    /**     * Common methods of the fingerprint module. This *must* be the first member     * of fingerprint_module as users of this structure will cast a hw_module_t     * to fingerprint_module pointer in contexts where it's known     * the hw_module_t references a fingerprint_module.     */    struct hw_module_t common;} fingerprint_module_t;#endif  /* ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H */



/hardware/libhardware/modules/fingerprint/fingerprint.c

-------------------------------------------------------------------------------------------

fingerprint.c

/* * 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 "FingerprintHal"#include #include #include #include #include #include static int fingerprint_close(hw_device_t *dev){    if (dev) {        free(dev);        return 0;    } else {        return -1;    }}static uint64_t fingerprint_pre_enroll(struct fingerprint_device __unused *dev) {    return FINGERPRINT_ERROR;}static int fingerprint_enroll(struct fingerprint_device __unused *dev,                                const hw_auth_token_t __unused *hat,                                uint32_t __unused gid,                                uint32_t __unused timeout_sec) {    return FINGERPRINT_ERROR;}static uint64_t fingerprint_get_auth_id(struct fingerprint_device __unused *dev) {    return FINGERPRINT_ERROR;}static int fingerprint_cancel(struct fingerprint_device __unused *dev) {    return FINGERPRINT_ERROR;}static int fingerprint_remove(struct fingerprint_device __unused *dev,                                uint32_t __unused gid, uint32_t __unused fid) {    return FINGERPRINT_ERROR;}static int fingerprint_set_active_group(struct fingerprint_device __unused *dev,                                        uint32_t __unused gid, const char __unused *store_path) {    return FINGERPRINT_ERROR;}static int fingerprint_authenticate(struct fingerprint_device __unused *dev,                                    uint64_t __unused operation_id, __unused uint32_t gid) {    return FINGERPRINT_ERROR;}static int set_notify_callback(struct fingerprint_device *dev,                                fingerprint_notify_t notify) {    /* Decorate with locks */    dev->notify = notify;    return FINGERPRINT_ERROR;}static int fingerprint_open(const hw_module_t* module, const char __unused *id,                            hw_device_t** device){    if (device == NULL) {        ALOGE("NULL device on open");        return -EINVAL;    }    fingerprint_device_t *dev = malloc(sizeof(fingerprint_device_t));    memset(dev, 0, sizeof(fingerprint_device_t));    dev->common.tag = HARDWARE_DEVICE_TAG;    dev->common.version = FINGERPRINT_MODULE_API_VERSION_2_0;    dev->common.module = (struct hw_module_t*) module;    dev->common.close = fingerprint_close;    dev->pre_enroll = fingerprint_pre_enroll;    dev->enroll = fingerprint_enroll;    dev->get_authenticator_id = fingerprint_get_auth_id;    dev->cancel = fingerprint_cancel;    dev->remove = fingerprint_remove;    dev->set_active_group = fingerprint_set_active_group;    dev->authenticate = fingerprint_authenticate;    dev->set_notify = set_notify_callback;    dev->notify = NULL;    *device = (hw_device_t*) dev;    return 0;}static struct hw_module_methods_t fingerprint_module_methods = {    .open = fingerprint_open,};fingerprint_module_t HAL_MODULE_INFO_SYM = {    .common = {        .tag                = HARDWARE_MODULE_TAG,        .module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,        .hal_api_version    = HARDWARE_HAL_API_VERSION,        .id                 = FINGERPRINT_HARDWARE_MODULE_ID,        .name               = "Demo Fingerprint HAL",        .author             = "The Android Open Source Project",        .methods            = &fingerprint_module_methods,    },};



更多相关文章

  1. android SDK系统图片资源的路径。
  2. Android P 指纹 Framework
  3. 2011.09.09 ——— android 2.2 修改安装路径
  4. 更改Android AVD模拟器创建路径位置的方法
  5. Android 设备指纹
  6. Android 存储路径浅析
  7. android 安卓 开发 图片库获得图片的绝对路径
  8. 修改 Android AVD 创建路径

随机推荐

  1. Android(安卓)学习之 LayoutInflater
  2. 第一章 andriod studio 安装与环境搭建
  3. Android(安卓)View的绘制过程复习
  4. android 关于程序升级问题
  5. android背景选择器selector用法汇总
  6. Android里面用XML定义菜单资源
  7. Android(安卓)软键盘盖住输入框的问题
  8. csr8811蓝牙芯片porting总结
  9. Android常用控件之悬浮窗(Service实现)
  10. EditText 的常用属性与解释