Android M 指纹框架

2016-12-30 07:37:19来源:CSDN作者:devwang_com人点击


几个路径:

/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

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


/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<Fingerprint> 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<UserInfo> 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<Fingerprint> 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<Fingerprint> mFingerprints = new ArrayList<Fingerprint>();    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<Fingerprint> 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<Fingerprint> getCopy(ArrayList<Fingerprint> array) {        ArrayList<Fingerprint> result = new ArrayList<Fingerprint>(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<Fingerprint> 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<FingerprintsUserState> mUsers = new SparseArray<>();    public static FingerprintUtils getInstance() {        synchronized (sInstanceLock) {            if (sInstance == null) {                sInstance = new FingerprintUtils();            }        }        return sInstance;    }    private FingerprintUtils() {    }    public List<Fingerprint> 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<Fingerprint> CREATOR            = new Parcelable.Creator<Fingerprint>() {        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. * <p> * 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 <a href="{@docRoot}training/articles/keystore.html">Android Keystore     *         facility</a>.     * @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<Fingerprint> 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<Fingerprint> 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<Fingerprint> 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 <cutils/log.h>#include <utils/Log.h>#include <binder/IPCThreadState.h>#include <binder/IServiceManager.h>#include <binder/PermissionCache.h>#include <utils/String16.h>#include <keystore/IKeystoreService.h>#include <keystore/keystore.h> // for error codes#include <hardware/hardware.h>#include <hardware/fingerprint.h>#include <hardware/hw_auth_token.h>#include "FingerprintDaemonProxy.h"int main() {    ALOGI("Starting " LOG_TAG);    android::sp<android::IServiceManager> serviceManager = android::defaultServiceManager();    android::sp<android::FingerprintDaemonProxy> 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 <binder/IServiceManager.h>#include <hardware/hardware.h>#include <hardware/fingerprint.h>#include <hardware/hw_auth_token.h>#include <keystore/IKeystoreService.h>#include <keystore/keystore.h> // for error codes#include <utils/Log.h>#include "FingerprintDaemonProxy.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>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<IFingerprintDaemonCallback> 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<const uint8_t *>(&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<IFingerprintDaemonCallback>& 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<const hw_auth_token_t*>(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;i<VENDOR_LIST_COUNT;i++){                vendor=&vendor_list[i];                int res =access(vendor->dev_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<const fingerprint_module_t*>(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<fingerprint_device_t*>(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<int64_t>(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<hw_device_t*>(mDevice)))) {        ALOGE("Can't close fingerprint module, error: %d", err);        return err;    }    mDevice = NULL;    return 0;}void FingerprintDaemonProxy::binderDied(const wp<IBinder>& 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<IFingerprintDaemonCallback>& 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<IBinder>& 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<IFingerprintDaemonCallback> 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 <inttypes.h>#include <binder/IPCThreadState.h>#include <binder/IServiceManager.h>#include <binder/PermissionCache.h>#include <utils/String16.h>#include <utils/Looper.h>#include <keystore/IKeystoreService.h>#include <keystore/keystore.h> // for error code#include <hardware/hardware.h>#include <hardware/fingerprint.h>#include <hardware/hw_auth_token.h>#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<const uint8_t *>(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<const uint8_t *>(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<IFingerprintDaemonCallback> callback =                    interface_cast<IFingerprintDaemonCallback>(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 <binder/IInterface.h>#include <binder/Parcel.h>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<IFingerprintDaemonCallback>& 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<IFingerprintDaemon> {    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 <stdint.h>#include <sys/types.h>#include <utils/Log.h>#include <binder/Parcel.h>#include "IFingerprintDaemonCallback.h"namespace android {class BpFingerprintDaemonCallback : public BpInterface<IFingerprintDaemonCallback>{public:    BpFingerprintDaemonCallback(const sp<IBinder>& impl) :            BpInterface<IFingerprintDaemonCallback>(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 <inttypes.h>#include <utils/Errors.h>#include <binder/IInterface.h>#include <binder/Parcel.h>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 <hardware/hw_auth_token.h>#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 <errno.h>#include <malloc.h>#include <string.h>#include <cutils/log.h>#include <hardware/hardware.h>#include <hardware/fingerprint.h>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,    },};



最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台