指纹识别的深入理解

本文深入探讨指纹识别的内部运作,重点关注AuthenticationClient对象的生命周期。在每次指纹识别过程中,client对象保持独立。当识别失败,client对象依然存在,允许继续尝试。若识别成功或连续5次失败,client会在特定条件下被移除,进入lockout模式,阻止进一步的识别操作。通过handleAuthenticated和handleFailedAttempt方法,client被停止并清除,确保系统资源的有效管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

地点:FingerprintService.java/AuthenticationClient.java
人物:AuthenticationClient和removeClient()(=null)

 AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token, receiver, mCurrentUserId, groupId, opId, restricted, opPackageName, bundle, dialogReceiver, mStatusBarService) {
                @Override //p
                public void onStart() {
                    try {
                        mActivityManager.registerTaskStackListener(mTaskStackListener);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Could not register task stack listener", e);
                    }
                }
                @Override //p
                public void onStop() {
                    try {
                        mActivityManager.unregisterTaskStackListener(mTaskStackListener);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Could not unregister task stack listener", e);
                    }
                }
    
                @Override
                public int handleFailedAttempt() {
                    final int currentUser = ActivityManager.getCurrentUser();
                    mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1);
                    mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false);
   

                 final int lockoutMode = getLockoutMode();
                    if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
                        mPerformanceStats.permanentLockout++;
                } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
                    mPerformanceStats.lockout++;
                }

                // Failing multiple times will continue to push out the lockout time
                if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
                    scheduleLockoutResetForUser(currentUser);
                    return lockoutMode;
                }
                return AuthenticationClient.LOCKOUT_NONE;
        }

        @Override
        public void resetFailedAttempts() {
            FingerprintService.this.resetFailedAttemptsForUser(true /* clearAttemptCounter */,
                    ActivityManager.getCurrentUser());
        }

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

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

理论上说,每调用一次authenticate接口就会创建一次AuthenticationClient对象,每个client之前具有独立性。

1.前面一次识别不成功,还可以继续识别,这个过程中client发生变化了吗?为什么

2.识别成功后,本次的client去哪儿了

3.请面5次识别失败,本次的client去哪儿了?

/**
     * Calls fingerprint HAL to switch states to the new task. If there's already a current task,
     * it calls cancel() and sets mPendingClient to begin when the current task finishes
     * ({@link FingerprintManager#FINGERPRINT_ERROR_CANCELED}).
     * @param newClient the new client that wants to connect
     * @param initiatedByClient true for authenticate, remove and enroll
     */
    private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
        ClientMonitor currentClient = mCurrentClient;
        if (currentClient != null) {
            if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
            if (currentClient instanceof InternalEnumerateClient ||
                    currentClient instanceof InternalRemovalClient) {
                // This condition means we're currently running internal diagnostics to
                // remove extra fingerprints in the hardware and/or the software
                // TODO: design an escape hatch in case client never finishes
            }
            else {//client冲掉了
                currentClient.stop(initiatedByClient/*useless*/);//通知底层cancel 
            }
            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 + ")");
            notifyClientActiveCallbacks(true);

            newClient.start();//为 newClient开启sensor扫描
        }
    }

指纹识别的结果会反馈到这里(调用下面的函数)

protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
        ArrayList<Byte> token) {
    ClientMonitor client = mCurrentClient;
    if (fingerId != 0) {
        // Ugh...
        final byte[] byteToken = new byte[token.size()];
        for (int i = 0; i < token.size(); i++) {
            byteToken[i] = token.get(i);
        }
        // Send to Keystore
        KeyStore.getInstance().addAuthToken(byteToken);
    }
    if (client != null && client.onAuthenticated(fingerId, groupId)) {
        removeClient(client);
    }
    if (fingerId != 0) {
        mPerformanceStats.accept++;
    } else {
        mPerformanceStats.reject++;
    }
}

看到removeClient

private void removeClient(ClientMonitor client) {
        if (client != null) {
            client.destroy();//
            if (client != mCurrentClient && mCurrentClient != null) {
                Slog.w(TAG, "Unexpected client: " + client.getOwnerString() + "expected: "
                        + mCurrentClient != null ? mCurrentClient.getOwnerString() : "null");
            }
        }
        if (mCurrentClient != null) {
            if (DEBUG) Slog.v(TAG, "Done with client: " + client.getOwnerString());
            if (deviceName.equals("bbb100")) {
   /* If there is a pending client, don't turn off the light, because startClient will run soon for it. */
                Slog.v(TAG, "FpLight(off) in removeClient\n");
                mHandler.removeCallbacks(mRestartFpAnimateRunnable);
                requestFpLight(false);
            }
            mCurrentClient = null;
        }
        if (mPendingClient == null) {
            notifyClientActiveCallbacks(false);
        }
    }

看到ClientMonitor

 public void destroy() {
        if (mToken != null) {
            try {
                mToken.unlinkToDeath(this, 0);
            } catch (NoSuchElementException e) {
                // TODO: remove when duplicate call bug is found
                Slog.e(TAG, "destroy(): " + this + ":", new Exception("here"));
            }
            mToken = null;
        }
        mReceiver = null;
    }

看到AuthenticationClient
关注返回值情况:

@Override
public boolean onAuthenticated(int fingerId, int groupId) {
    boolean result = false;
    boolean authenticated = fingerId != 0;
     
    //进入了lockout模式或者识别成功返回true,导致client移除;(没进入lockout)识别失败返回false,不移除client
…...
}

Note:指纹的识别,录入等操作需要同时具备两个条件:
1.指纹底层处于image模式(没有cancel)

2.此时的client非null。(只有在存在的client的基础上才能做识别,录入等操作)

对于lockout模式,第五次识别失败后,调用 handleAuthenticated时,将导致client移除。将无法继续指纹的识别操作。

 private IBiometricsFingerprintClientCallback mDaemonCallback =
            new IBiometricsFingerprintClientCallback.Stub() {
       @Override
        public void onAuthenticated(final long deviceId, final int fingerId, final int groupId,
                ArrayList<Byte> token) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    handleAuthenticated(deviceId, fingerId, groupId, token);
                }
            });
        }
       @Override
        public void onError(final long deviceId, final int error, final int vendorCode) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    handleError(deviceId, error, vendorCode);
                }
            });
        }
   …...
}

从handleAuthenticated,再将目光投向AuthenticationClient,通过逻辑,handleFailedAttempt() 让进入lockout模式,接着stop(false)—>cancel (daemon.cancel())----> handleError–>onError返回值为 true---->removeClient (client)(指纹停止工作,client清除); 同时onAuthenticated返回值为true—>removeClient(client);(client清除) 通过分析可以确定是 handleAuthenticated先将导致removeClient(client)使得client清除,后面的 removeClient由于Client已经为null,,其实将没有任何实际意义的操作

 protected void handleError(long deviceId, int error, int vendorCode) {
        ClientMonitor client = mCurrentClient;
        if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) {
            resetEnumerateState();
        }
        if (client != null && client.onError(error, vendorCode)) {
            removeClient(client);
        }
…...
//ClientMonitor.java
    public boolean onError(int error, int vendorCode) {
        if (mReceiver != null) {
            try {
                mReceiver.onError(getHalDeviceId(), error, vendorCode);
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed to invoke sendError:", e);
            }
        }
        return true; // errors always remove current client
    }

Note:通过authenticate等API让指纹工作起来后,除非对它cancel,让它停止工作,否则它将一直处于工作状态中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值