Servicio de huellas digitales Android7.0 Introducción a FingerprintService

El servicio de huellas digitales es un servicio relativamente simple en el sistema Android (en comparación con AMS, WMS, etc.) y también es relativamente independiente. La función incluye varios puntos

  • Entrada y eliminación de huellas digitales
  • Autenticación de huellas digitales
  • La política de seguridad de huellas digitales (determinación de conteo de errores) es la
    misma que la de otros servicios del sistema. La aplicación se comunica con FingerprintService a través de FingerprintManager. Además de las funciones mencionadas anteriormente, FingerprintManager proporciona algunas otras interfaces. Las interfaces importantes requerirán el sistema Nivel de autoridad, y no es una API pública (entrada de huellas digitales, eliminación, cambio de nombre, recuento de errores de reinicio, etc.)

 

    /**
     * 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) {
            throw e.rethrowFromSystemServer();
        }
        return null;
    }

    /**
     * @hide
     */
    @RequiresPermission(allOf = {
            USE_FINGERPRINT,
            INTERACT_ACROSS_USERS})
    public boolean hasEnrolledFingerprints(int userId) {
        if (mService != null) try {
            return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        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) {
                throw e.rethrowFromSystemServer();
            }
        } else {
            Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
        }
        return false;
    }

Proceso de inicio de FingerprintService

FingerprintService se crea e inicializa en el servidor del sistema, e iniciará este servicio cuando detecte que el teléfono admite la función de huella digital

 

...
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
     mSystemServiceManager.startService(FingerprintService.class);
  }
...

Después de la inicialización, FingerprintService establecerá comunicación con la capa HAL, es decir, se conectará a fingerprintd y obtendrá el objeto IFingerprintDaemon (carpeta) para la comunicación.

 

public void onStart() {
        publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
        IFingerprintDaemon daemon = getFingerprintDaemon();
        listenForUserSwitches();
    }

 

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(), null);
                    } else {
                        Slog.w(TAG, "Failed to open Fingerprint HAL!");
                        MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
                        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;
    }

Esencialmente, aparte de las políticas relacionadas con la seguridad, la función de huella digital se implementa mediante hardware. FingerprintService solo actúa como un mensajero para la capa java de marco y la capa nativa, por lo que la identificación, entrada y monitoreo de huellas digitales se envían a huella digital. Manda y obtén el resultado correspondiente

Proceso de monitoreo y autenticación de huellas digitales

Tome la autenticación de huellas digitales como ejemplo para introducir este proceso. El proceso de entrada y eliminación es similar a la autenticación, y la descripción no se repite.

FingerprintManager

 

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));
            }
        }
    }

Se puede ver que al final, el mensaje todavía se envía a FingerprintService, pero la función de habilitar la autenticación de huellas digitales ha pasado en dos parámetros más importantes, uno es el objeto CancellationSignal, que se utiliza para cancelar la autenticación de huellas digitales, y el otro es el objeto de devolución de llamada de la autenticación de huellas digitales, AuthenticationCallback

 

public static abstract class AuthenticationCallback {
        public void onAuthenticationError(int errorCode, CharSequence errString) { }

        public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }

        public void onAuthenticationSucceeded(AuthenticationResult result) { }

        public void onAuthenticationFailed() { }

        public void onAuthenticationAcquired(int acquireInfo) {}
    };

También puede conocer la función mirando el nombre de la función. Representan respectivamente los resultados de la devolución de llamada durante la autenticación de huellas digitales (éxito, falla, detección de huellas digitales, excepción de autenticación, etc.). Los parámetros contienen información específica, que tiene constantes correspondientes en FingerprintManager. Definición, interesado puede ver el código

Servicio de huellas digitales

 

public void authenticate(final IBinder token, final long opId, final int groupId,
                final IFingerprintServiceReceiver receiver, final int flags,
                final String opPackageName) {
            final int callingUid = Binder.getCallingUid();
            final int callingUserId = UserHandle.getCallingUserId();
            final int pid = Binder.getCallingPid();
            final boolean restricted = isRestricted();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (!canUseFingerprint(opPackageName, true /* foregroundOnly */,
                            callingUid, pid)) {
                        if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
                        return;
                    }

                    MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);

                    // Get performance stats object for this user.
                    HashMap<Integer, PerformanceStats> pmap
                            = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
                    PerformanceStats stats = pmap.get(mCurrentUserId);
                    if (stats == null) {
                        stats = new PerformanceStats();
                        pmap.put(mCurrentUserId, stats);
                    }
                    mPerformanceStats = stats;

                    startAuthentication(token, opId, callingUserId, groupId, receiver,
                            flags, restricted, opPackageName);
                }
            });
        }

Se verificará el nombre del paquete, el ID de usuario y si el proceso de solicitud está en primer plano en el frente, continúe viendo

 

private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
                IFingerprintServiceReceiver receiver, int flags, boolean restricted,
                String opPackageName) {
        updateActiveGroup(groupId, opPackageName);

        if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");

        AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
                receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) {
            @Override
            public boolean handleFailedAttempt() {
                mFailedAttempts++;
                if (mFailedAttempts == MAX_FAILED_ATTEMPTS) {
                    mPerformanceStats.lockout++;
                }
                if (inLockoutMode()) {
                    // Failing multiple times will continue to push out the lockout time.
                    scheduleLockoutReset();
                    return true;
                }
                return false;
            }

            @Override
            public void resetFailedAttempts() {
                FingerprintService.this.resetFailedAttempts();
            }

            @Override
            public void notifyUserActivity() {
                FingerprintService.this.userActivity();
            }

            @Override
            public IFingerprintDaemon getFingerprintDaemon() {
                return FingerprintService.this.getFingerprintDaemon();
            }
        };

        if (inLockoutMode()) {
            Slog.v(TAG, "In lockout mode; disallowing authentication");
            // Don't bother starting the client. Just send the error message.
            if (!client.onError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
                Slog.w(TAG, "Cannot send timeout message to client");
            }
            return;
        }
        startClient(client, true /* initiatedByClient */);
    }

AuthenticationClient hereda de ClientMonitor y se utiliza para manejar transacciones funcionales relacionadas con la autenticación de huellas digitales. Otras subclases de ClientMonitor, como RemovalMonior y EnrollMonitor, también. ClientMonitor se comunicará directamente con fingerprintd. Su núcleo es llamar a su método start () o stop ().
Para AuthenticationClient En términos de

 

private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
        ClientMonitor currentClient = mCurrentClient;
        if (currentClient != null) {
            if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
            currentClient.stop(initiatedByClient);
            mPendingClient = newClient;
            mHandler.removeCallbacks(mResetClientState);
            mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
        } else if (newClient != null) {
            mCurrentClient = newClient;
            if (DEBUG) Slog.v(TAG, "starting client "
                    + newClient.getClass().getSuperclass().getSimpleName()
                    + "(" + newClient.getOwnerString() + ")"
                    + ", initiatedByClient = " + initiatedByClient + ")");
            newClient.start();
        }
    }

 

public int start() {
        IFingerprintDaemon daemon = getFingerprintDaemon();
        if (daemon == null) {
            Slog.w(TAG, "start authentication: no fingeprintd!");
            return ERROR_ESRCH;
        }
        try {
            final int result = daemon.authenticate(mOpId, getGroupId());
            if (result != 0) {
                Slog.w(TAG, "startAuthentication failed, result=" + result);
                MetricsLogger.histogram(getContext(), "fingeprintd_auth_start_error", result);
                onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
                return result;
            }
            if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is authenticating...");
        } catch (RemoteException e) {
            Slog.e(TAG, "startAuthentication failed", e);
            return ERROR_ESRCH;
        }
        return 0; // success
    }

Después de enviar el comando de autenticación a la capa inferior, solo necesita esperar el resultado de la autenticación. Anteriormente dijimos que durante la inicialización, se establecerá la comunicación con huella digital. El núcleo es la siguiente línea de código

 

mDaemon.init(mDaemonCallback);

mDaemonCallback es un objeto de carpeta que acepta los resultados de la capa inferior y luego envía los resultados a la aplicación capa por capa a través de FingerprintService y FingerManager.

Algunos cambios en 8.0

Fingerprintd en 8.0 ha cambiado mucho, y ni siquiera se llama huella digital. Por supuesto, esto es una cuestión de capa nativa, no se discute aquí. Para FingerprintService, un cambio significativo es el ajuste de la política de seguridad

  • Antes de 8.0, la huella digital solo puede estar equivocada 5 veces. Cuando llegue a 5 veces, se prohibirá la autenticación de huellas digitales. Al mismo tiempo, se iniciará una cuenta regresiva de 30 segundos. Después de esperar el final, el recuento de errores se restablecerá y la autenticación continuará.
  • Después de 8.0, sigue contando 30 segundos por cada 5 errores. Sin embargo, después de 30 segundos, el conteo de errores no se borrará. Se ha agregado un límite de 20 veces a 8.0. Después de acumular 20 errores, no se puede utilizar la función de autenticación de huellas digitales. , El recuento de errores solo se puede restablecer con una contraseña

 

private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5;
private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20;


private int getLockoutMode() {
        if (mFailedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) {
            return AuthenticationClient.LOCKOUT_PERMANENT;
        } else if (mFailedAttempts > 0 && mTimedLockoutCleared == false &&
                (mFailedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) {
            return AuthenticationClient.LOCKOUT_TIMED;
        }
        return AuthenticationClient.LOCKOUT_NONE;
    }



Autor: Lonelyyy
enlace: https: //www.jianshu.com/p/6c625e4323a1
Fuente: libros de Jane
tienen derechos de autor por el autor. Para la reproducción comercial, comuníquese con el autor para obtener autorización, y para la reproducción no comercial, indique la fuente.

31 artículos originales publicados · Me gusta6 · Visitantes más de 10,000

Supongo que te gusta

Origin blog.csdn.net/u012824529/article/details/103744341
Recomendado
Clasificación