@Override public void onAuthenticationFailed() { listener.onFailure(AuthenticationFailureReason.AUTHENTICATION_FAILED, false, context.getString(R.string.fingerprint_not_recognized), TAG, FINGERPRINT_AUTHENTICATION_FAILED); } }
@Override public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { listener.onSuccess(TAG); }
private void fail(AuthenticationFailureReason reason, boolean fatal, String message, int status) { listener.onFailure(reason, fatal, message, TAG, status); if ((!fatal || reason == TIMEOUT) && restartPredicate.invoke(reason, restartCount)) { authenticate(cancellationSignal, listener, restartPredicate, restartCount + 1); } }
@Override public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { if (!restartPredicate.invoke(AuthenticationFailureReason.SENSOR_FAILED, restartCount++)) { cancellationSignal.cancel(); } listener.onFailure(AuthenticationFailureReason.SENSOR_FAILED, false, helpString, TAG, helpMsgId); }
@Override public void onFinished(int eventStatus) { switch (eventStatus) { case SpassFingerprint.STATUS_AUTHENTIFICATION_SUCCESS: case SpassFingerprint.STATUS_AUTHENTIFICATION_PASSWORD_SUCCESS: listener.onSuccess(TAG); return; case SpassFingerprint.STATUS_QUALITY_FAILED: fail(AuthenticationFailureReason.SENSOR_FAILED, false, R.string.fingerprint_acquired_partial, eventStatus); break; case SpassFingerprint.STATUS_SENSOR_FAILED: fail(AuthenticationFailureReason.SENSOR_FAILED, false, R.string.fingerprint_acquired_insufficient, eventStatus); break; case SpassFingerprint.STATUS_AUTHENTIFICATION_FAILED: fail(AuthenticationFailureReason.AUTHENTICATION_FAILED, false, R.string.fingerprint_not_recognized, eventStatus); break; case SpassFingerprint.STATUS_TIMEOUT_FAILED: fail(TIMEOUT, true, R.string.fingerprint_error_timeout, eventStatus); break; default: fail(AuthenticationFailureReason.UNKNOWN, true, R.string.fingerprint_error_hw_not_available, eventStatus); break; case SpassFingerprint.STATUS_USER_CANCELLED: // Don't send a cancelled message. break; } }
/** * Start an authentication request. * * @param listener The listener to be notified. * @param restartPredicate The predicate that determines whether to restart or not. */ public void authenticate(final AuthenticationListener listener, Reprint.RestartPredicate restartPredicate) { if (module == null || !module.isHardwarePresent()) { listener.onFailure(AuthenticationFailureReason.NO_HARDWARE, true, getString(R.string.fingerprint_error_hw_not_available), 0, 0); return; } if (!module.hasFingerprintRegistered()) { listener.onFailure(AuthenticationFailureReason.NO_FINGERPRINTS_REGISTERED, true, getString(R.string.fingerprint_not_recognized), 0, 0); return; } cancellationSignal.set(new CancellationSignal()); module.authenticate(cancellationSignal.get(), listener, restartPredicate); }
@Test public void successfulRequest() throws Exception { ts.requestMore(1); module.listener.onSuccess(module.TAG); final List<AuthenticationResult> events = ts.getOnNextEvents(); assertEquals(events.size(), 1); assertEquals(events.get(0).status, SUCCESS); ts.assertCompleted(); }
@Override public void onAuthenticationError(int errMsgId, CharSequence errString) { AuthenticationFailureReason failureReason = AuthenticationFailureReason.UNKNOWN; switch (errMsgId) { case FINGERPRINT_ERROR_HW_UNAVAILABLE: failureReason = AuthenticationFailureReason.HARDWARE_UNAVAILABLE; break; case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: case FINGERPRINT_ERROR_NO_SPACE: failureReason = AuthenticationFailureReason.SENSOR_FAILED; break; case FINGERPRINT_ERROR_TIMEOUT: failureReason = AuthenticationFailureReason.TIMEOUT; break; case FINGERPRINT_ERROR_LOCKOUT: failureReason = AuthenticationFailureReason.LOCKED_OUT; break; case FINGERPRINT_ERROR_CANCELED: // Don't send a cancelled message. return; } if (errMsgId == FINGERPRINT_ERROR_TIMEOUT && restartPredicate.invoke(failureReason, restartCount)) { authenticate(cancellationSignal, listener, restartPredicate, restartCount); } else { listener.onFailure(failureReason, true, errString, TAG, errMsgId); } }
@Test public void successfulRequest() throws Exception { ts.requestMore(1); module.listener.onSuccess(module.TAG); List<AuthenticationResult> events = ts.values(); assertEquals(events.size(), 1); assertEquals(events.get(0).status, SUCCESS); ts.assertComplete(); }
@Test public void failedRequest() throws Exception { verifyZeroInteractions(listener); module.listener.onFailure(AuthenticationFailureReason.AUTHENTICATION_FAILED, false, "", module.TAG, 0); verify(listener).onFailure(eq(AuthenticationFailureReason.AUTHENTICATION_FAILED), eq(false), anyString(), anyInt(), anyInt()); } }
@Test public void successfulRequestBackpressure() throws Exception { module.listener.onSuccess(module.TAG); ts.assertNoValues(); ts.requestMore(1); ts.assertValueCount(1); ts.assertComplete(); }
void authenticate(final CancellationSignal cancellationSignal, final AuthenticationListener listener, final Reprint.RestartPredicate restartPredicate, final int restartCount) throws SecurityException { final FingerprintManager fingerprintManager = fingerprintManager(); if (fingerprintManager == null) { listener.onFailure(AuthenticationFailureReason.UNKNOWN, true, context.getString(R.string.fingerprint_error_hw_not_available), TAG, FINGERPRINT_ERROR_CANCELED); return; } final FingerprintManager.AuthenticationCallback callback = new AuthCallback(restartCount, restartPredicate, cancellationSignal, listener); // Why getCancellationSignalObject returns an Object is unexplained final android.os.CancellationSignal signalObject = cancellationSignal == null ? null : (android.os.CancellationSignal) cancellationSignal.getCancellationSignalObject(); // Occasionally, an NPE will bubble up out of FingerprintManager.authenticate try { fingerprintManager.authenticate(null, signalObject, 0, callback, null); } catch (NullPointerException e) { logger.logException(e, "MarshmallowReprintModule: authenticate failed unexpectedly"); listener.onFailure(AuthenticationFailureReason.UNKNOWN, true, context.getString(R.string.fingerprint_error_unable_to_process), TAG, FINGERPRINT_ERROR_CANCELED); } }
@Test public void successfulRequestBackpressure() throws Exception { module.listener.onSuccess(module.TAG); ts.assertNoValues(); ts.requestMore(1); ts.assertValueCount(1); ts.assertCompleted(); }
listener.onFailure(AuthenticationFailureReason.NO_FINGERPRINTS_REGISTERED, true, context.getString(R.string.fingerprint_error_hw_not_available), TAG, STATUS_NO_REGISTERED_FINGERPRINTS); return; listener.onFailure(AuthenticationFailureReason.HARDWARE_UNAVAILABLE, true, context.getString(R.string.fingerprint_error_hw_not_available), TAG, STATUS_HW_UNAVAILABLE); return; } catch (Throwable t) { logger.logException(t, "SpassReprintModule: fingerprint identification would not start"); listener.onFailure(AuthenticationFailureReason.LOCKED_OUT, true, null, TAG, STATUS_LOCKED_OUT); return;
@Test public void nonFatalFailure() throws Exception { ts.requestMore(1); module.listener.onFailure(AuthenticationFailureReason.AUTHENTICATION_FAILED, false, "", module.TAG, 0); List<AuthenticationResult> events = ts.values(); assertEquals(events.size(), 1); assertEquals(events.get(0).status, NONFATAL_FAILURE); ts.assertNotTerminated(); }
@Test public void nonFatalFailure() throws Exception { ts.requestMore(1); module.listener.onFailure(AuthenticationFailureReason.AUTHENTICATION_FAILED, false, "", module.TAG, 0); final List<AuthenticationResult> events = ts.getOnNextEvents(); assertEquals(events.size(), 1); assertEquals(events.get(0).status, NONFATAL_FAILURE); ts.assertNoTerminalEvent(); }
@Test public void fatalFailure() throws Exception { ts.requestMore(1); module.listener.onFailure(AuthenticationFailureReason.AUTHENTICATION_FAILED, true, "", module.TAG, 0); final List<AuthenticationResult> events = ts.getOnNextEvents(); assertEquals(events.size(), 1); assertEquals(events.get(0).status, FATAL_FAILURE); ts.assertCompleted(); }
@Test public void fatalFailure() throws Exception { ts.requestMore(1); module.listener.onFailure(AuthenticationFailureReason.AUTHENTICATION_FAILED, true, "", module.TAG, 0); List<AuthenticationResult> events = ts.values(); assertEquals(events.size(), 1); assertEquals(events.get(0).status, FATAL_FAILURE); ts.assertComplete(); }