FileDocCategorySizeDatePackage
FingerprintManager.javaAPI DocAndroid 5.1 API9156Thu Mar 12 22:22:10 GMT 2015android.service.fingerprint

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.service.fingerprint;

import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;

/**
 * A class that coordinates access to the fingerprint hardware.
 * @hide
 */

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_PROCESSED = 102;
    private static final int MSG_ERROR = 103;
    private static final int MSG_REMOVED = 104;

    // Errors generated by layers above HAL
    public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10;

    // Message types.  Must agree with HAL (fingerprint.h)
    public static final int FINGERPRINT_ERROR = -1;
    public static final int FINGERPRINT_ACQUIRED = 1;
    public static final int FINGERPRINT_PROCESSED = 2;
    public static final int FINGERPRINT_TEMPLATE_ENROLLING = 3;
    public static final int FINGERPRINT_TEMPLATE_REMOVED = 4;

    // Error messages. Must agree with HAL (fingerprint.h)
    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
    public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;

    // FINGERPRINT_ACQUIRED messages.  Must agree with HAL (fingerprint.h)
    public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
    public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
    public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
    public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 4;
    public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 8;
    public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 16;

    private IFingerprintService mService;
    private FingerprintManagerReceiver mClientReceiver;
    private Context mContext;
    private IBinder mToken = new Binder();

    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (mClientReceiver != null) {
                switch(msg.what) {
                    case MSG_ENROLL_RESULT:
                        mClientReceiver.onEnrollResult(msg.arg1, msg.arg2);
                        break;
                    case MSG_ACQUIRED:
                        mClientReceiver.onAcquired(msg.arg1);
                        break;
                    case MSG_PROCESSED:
                        mClientReceiver.onProcessed(msg.arg1);
                        break;
                    case MSG_ERROR:
                        mClientReceiver.onError(msg.arg1);
                        break;
                    case MSG_REMOVED:
                        mClientReceiver.onRemoved(msg.arg1);
                }
            }
        }
    };

    /**
     * @hide
     */
    public FingerprintManager(Context context, IFingerprintService service) {
        mContext = context;
        mService = service;
        if (mService == null) {
            Slog.v(TAG, "FingerprintManagerService was null");
        }
    }

    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {

        public void onEnrollResult(int fingerprintId,  int remaining) {
            mHandler.obtainMessage(MSG_ENROLL_RESULT, fingerprintId, remaining).sendToTarget();
        }

        public void onAcquired(int acquireInfo) {
            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0).sendToTarget();
        }

        public void onProcessed(int fingerprintId) {
            mHandler.obtainMessage(MSG_PROCESSED, fingerprintId, 0).sendToTarget();
        }

        public void onError(int error) {
            mHandler.obtainMessage(MSG_ERROR, error, 0).sendToTarget();
        }

        public void onRemoved(int fingerprintId) {
            mHandler.obtainMessage(MSG_REMOVED, fingerprintId, 0).sendToTarget();
        }
    };

    /**
     * Determine whether the user has at least one fingerprint enrolled and enabled.
     *
     * @return true if at least one is enrolled and enabled
     */
    public boolean enrolledAndEnabled() {
        ContentResolver res = mContext.getContentResolver();
        return Settings.Secure.getInt(res, "fingerprint_enabled", 0) != 0
                && FingerprintUtils.getFingerprintIdsForUser(res, getCurrentUserId()).length > 0;
    }

    /**
     * Start the enrollment process.  Timeout dictates how long to wait for the user to
     * enroll a fingerprint.
     *
     * @param timeout
     */
    public void enroll(long timeout) {
        if (mServiceReceiver == null) {
            sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
            return;
        }
        if (mService != null) try {
            mService.enroll(mToken, timeout, getCurrentUserId());
        } catch (RemoteException e) {
            Log.v(TAG, "Remote exception while enrolling: ", e);
            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
        }
    }

    /**
     * Remove the given fingerprintId from the system.  FingerprintId of 0 has special meaning
     * which is to delete all fingerprint data for the current user. Use with caution.
     * @param fingerprintId
     */
    public void remove(int fingerprintId) {
        if (mServiceReceiver == null) {
            sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
            return;
        }
        if (mService != null) {
            try {
                mService.remove(mToken, fingerprintId, getCurrentUserId());
            } catch (RemoteException e) {
                Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e);
            }
        } else {
            Log.w(TAG, "remove(): Service not connected!");
            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
        }
    }

    /**
     * Starts listening for fingerprint events.  When a finger is scanned or recognized, the
     * client will be notified via the callback.
     */
    public void startListening(FingerprintManagerReceiver receiver) {
        mClientReceiver = receiver;
        if (mService != null) {
            try {
                mService.startListening(mToken, mServiceReceiver, getCurrentUserId());
            } catch (RemoteException e) {
                Log.v(TAG, "Remote exception in startListening(): ", e);
            }
        } else {
            Log.w(TAG, "startListening(): Service not connected!");
            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
        }
    }

    private int getCurrentUserId() {
        try {
            return ActivityManagerNative.getDefault().getCurrentUser().id;
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get current user id\n");
            return UserHandle.USER_NULL;
        }
    }

    /**
     * Stops the client from listening to fingerprint events.
     */
    public void stopListening() {
        if (mService != null) {
            try {
                mService.stopListening(mToken, getCurrentUserId());
                mClientReceiver = null;
            } catch (RemoteException e) {
                Log.v(TAG, "Remote exception in stopListening(): ", e);
            }
        } else {
            Log.w(TAG, "stopListening(): Service not connected!");
            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
        }
    }

    public void enrollCancel() {
        if (mServiceReceiver == null) {
            sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
            return;
        }
        if (mService != null) {
            try {
                mService.enrollCancel(mToken, getCurrentUserId());
                mClientReceiver = null;
            } catch (RemoteException e) {
                Log.v(TAG, "Remote exception in enrollCancel(): ", e);
                sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
            }
        } else {
            Log.w(TAG, "enrollCancel(): Service not connected!");
        }
    }

    private void sendError(int msg, int arg1, int arg2) {
        mHandler.obtainMessage(msg, arg1, arg2);
    }
}