/* * Copyright (c) 2016 Aitor Viana Sanchez * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and * associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software * is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.aitorvs.android.fingerlock; import android.Manifest; import android.annotation.TargetApi; import android.hardware.fingerprint.FingerprintManager; import android.os.Build; import android.os.CancellationSignal; import android.support.annotation.RequiresPermission; import com.aitorvs.android.fingerlock.FingerLock; import com.aitorvs.android.fingerlock.FingerLockResultCallback; @TargetApi(Build.VERSION_CODES.M) class FingerprintAuthHandler extends FingerprintManager.AuthenticationCallback { private final FingerprintManager.CryptoObject mCryptoObject; private CancellationSignal mCancellationSignal; private FingerLockResultCallback mCallback; // flags when the operation is canceled internally private boolean mSelfCancelled; FingerprintAuthHandler(FingerprintManager.CryptoObject cryptoObject, FingerLockResultCallback callback) { mCryptoObject = cryptoObject; mCallback = callback; } public boolean isReady() { return mCancellationSignal == null; } public boolean isStarted() { // authentication already started and scanning return mCancellationSignal != null; } @RequiresPermission(Manifest.permission.USE_FINGERPRINT) public void start(FingerprintManager fpm) { if (fpm == null || mCallback == null) { // FIXME: 23/05/16 report error? return; } mSelfCancelled = false; mCancellationSignal = new CancellationSignal(); fpm.authenticate(mCryptoObject, mCancellationSignal, 0 /* flags */, this, null);; } public void stop(boolean self) { if (mCancellationSignal != null) { mSelfCancelled = self; mCancellationSignal.cancel(); mCancellationSignal = null; } } @Override public void onAuthenticationError(int errorCode, CharSequence errString) { super.onAuthenticationError(errorCode, errString); if (mCallback != null && !mSelfCancelled) { mCallback.onFingerLockError(FingerLock.FINGERPRINT_UNRECOVERABLE_ERROR, new Exception(errString.toString())); } } @Override public void onAuthenticationHelp(int helpCode, CharSequence helpString) { super.onAuthenticationHelp(helpCode, helpString); if (mCallback != null) { mCallback.onFingerLockError(FingerLock.FINGERPRINT_ERROR_HELP, new Exception(helpString.toString())); } } @Override public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { super.onAuthenticationSucceeded(result); if (mCallback != null) { mCallback.onFingerLockAuthenticationSucceeded(); } // auto stop stop(true); } @Override public void onAuthenticationFailed() { super.onAuthenticationFailed(); if (mCallback != null) { mCallback.onFingerLockError(FingerLock.FINGERPRINT_NOT_RECOGNIZED, new Exception("Fingerprint not recognized, try again.")); } } }