生物识别指纹_生物指纹识别技术

生物识别指纹_生物指纹识别技术锁屏要使用指纹解锁,首先要注册指纹服务,我看过的一些大厂项目中,实际上是在KeyguardUpdate.java类中发起注册的,一般是根据当前状态,是不是已经处于上锁状态(侧边指纹机器,是不等上锁即进行指纹服务注册,屏下指纹需要等上锁后,才发起指纹服务注册)。………………………

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

锁屏要使用指纹解锁,首先要注册指纹服务,我看过的一些大厂项目中,实际上是在KeyguardUpdate.java类中发起注册的,一般是根据当前状态,是不是已经处于上锁状态(侧边指纹机器,是不等上锁即进行指纹服务注册,屏下指纹需要等上锁后,才发起指纹服务注册)。

具体代码一般就是KeyguardUpdateMonitor类下的

private void startListeningForFingerprint() {
        final int userId = getCurrentUser();
        final boolean unlockPossible = isUnlockWithFingerprintPossible(userId);
        if (mFingerprintCancelSignal != null) {
            Log.e(TAG, "Cancellation signal is not null, high chance of bug in fp auth lifecycle"
                    + " management. FP state: " + mFingerprintRunningState
                    + ", unlockPossible: " + unlockPossible);
        }

        if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING) {
            setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
            return;
        }
        if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
            // Waiting for restart via handleFingerprintError().
            return;
        }
        if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");

        if (unlockPossible) {
            mFingerprintCancelSignal = new CancellationSignal();

            if (isEncryptedOrLockdown(userId)) {
                mFpm.detectFingerprint(mFingerprintCancelSignal, mFingerprintDetectionCallback,
                        userId);
            } else {
                mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
                        mFingerprintAuthenticationCallback, null /* handler */,
                        FingerprintManager.SENSOR_ID_ANY, userId, 0 /* flags */);
            }
            setFingerprintRunningState(BIOMETRIC_STATE_RUNNING);
        }
    }

mFpm变量就是FingerPrintManager类对象实例。见第27行,会调用指纹服务注册流程。

下面看看FingerPrintManager类的authenticate方法

@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
            @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId,
            int flags) {

        FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
                AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE,
                mContext.getApplicationInfo().uid,
                mContext.getApplicationInfo().targetSdkVersion);

        if (callback == null) {
            throw new IllegalArgumentException("Must supply an authentication callback");
        }

        if (cancel != null && cancel.isCanceled()) {
            Slog.w(TAG, "authentication already canceled");
            return;
        }

        final boolean ignoreEnrollmentState = flags == 0 ? false : true;

        if (mService != null) {
            try {
                useHandler(handler);
                mAuthenticationCallback = callback;
                mCryptoObject = crypto;
                final long operationId = crypto != null ? crypto.getOpId() : 0;
                final long authId = mService.authenticate(mToken, operationId, sensorId, userId,
                        mServiceReceiver, mContext.getOpPackageName(), ignoreEnrollmentState);
                if (cancel != null) {
                    cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Remote exception while authenticating: ", e);
                // 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(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
                                0 /* vendorCode */));
            }
        }
    }

见第28行,就是进行指纹服务注册,继续往下看,就是调用mService.authenticate 方法

下面看看变量mService对象是哪个?通过souce insight 工具搜索

有这个定义private IFingerprintService mService;

然后继续往下找在哪儿定义的

public FingerprintManager(Context context, IFingerprintService service) {
        mContext = context;
        mService = service;
        if (mService == null) {
            Slog.v(TAG, "FingerprintService was null");
        }
        mHandler = new MyHandler(context);
    }

在其他地方初始化 FingerprintManager的时候传进来的,然后在KeyguardUpdate类中找到以下代码

if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
            mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
        }

显然mFpm是个系统服务,继续往下找。搜到类SystemServieRegistry.java

registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class,
                new CachedServiceFetcher<FingerprintManager>() {
            @Override
            public FingerprintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                final IBinder binder;
                if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
                    binder = ServiceManager.getServiceOrThrow(Context.FINGERPRINT_SERVICE);
                } else {
                    binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE);
                }
                IFingerprintService service = IFingerprintService.Stub.asInterface(binder);
                return new FingerprintManager(ctx.getOuterContext(), service);
            }});

第11行,从代码来看,可以发现这里用到Binder调用技术,即aidl

service 就是继承IFingerprintService的FingerprintService类。

就是说,上面的mService 就是 要到FingerprintService类中去寻找对象实例了。

然后来到FingerprintService类,查找对应的authenticate方法

        @SuppressWarnings("deprecation")
        @Override // Binder call
        public long authenticate(final IBinder token, final long operationId,
                final int sensorId, final int userId, final IFingerprintServiceReceiver receiver,
                final String opPackageName, boolean ignoreEnrollmentState) {
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int callingUserId = UserHandle.getCallingUserId();

            if (!canUseFingerprint(opPackageName, true /* requireForeground */, callingUid,
                    callingPid, callingUserId)) {
                Slog.w(TAG, "Authenticate rejecting package: " + opPackageName);
                return -1;
            }

            // Keyguard check must be done on the caller's binder identity, since it also checks
            // permission.
            final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName);

            // Clear calling identity when checking LockPatternUtils for StrongAuth flags.
            long identity = Binder.clearCallingIdentity();
            try {
                if (isKeyguard && Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
                    // If this happens, something in KeyguardUpdateMonitor is wrong.
                    // SafetyNet for b/79776455
                    EventLog.writeEvent(0x534e4554, "79776455");
                    Slog.e(TAG, "Authenticate invoked when user is encrypted or lockdown");
                    return -1;
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }

            final boolean restricted = getContext().checkCallingPermission(MANAGE_FINGERPRINT)
                    != PackageManager.PERMISSION_GRANTED;
            final int statsClient = isKeyguard ? BiometricsProtoEnums.CLIENT_KEYGUARD
                    : BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;

            final Pair<Integer, ServiceProvider> provider;
            if (sensorId == FingerprintManager.SENSOR_ID_ANY) {
                provider = getSingleProvider();
            } else {
                Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
                provider = new Pair<>(sensorId, getProviderForSensor(sensorId));
            }
            if (provider == null) {
                Slog.w(TAG, "Null provider for authenticate");
                return -1;
            }

            final FingerprintSensorPropertiesInternal sensorProps =
                    provider.second.getSensorProperties(sensorId);
            if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName)
                    && sensorProps != null && sensorProps.isAnyUdfpsType()) {
                identity = Binder.clearCallingIdentity();
                try {
                    return authenticateWithPrompt(operationId, sensorProps, userId, receiver,
                            ignoreEnrollmentState);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
            return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
                    0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName,
                    restricted, statsClient, isKeyguard);
        }

先看第41行代码

provider = getSingleProvider();

@Nullable
    private Pair<Integer, ServiceProvider> getSingleProvider() {
        final List<FingerprintSensorPropertiesInternal> properties = getSensorProperties();
        if (properties.isEmpty()) {
            Slog.e(TAG, "No providers found");
            return null;
        }

        // Theoretically we can just return the first provider, but maybe this is easier to
        // understand.
        final int sensorId = properties.get(0).sensorId;
        for (ServiceProvider provider : mServiceProviders) {
            if (provider.containsSensor(sensorId)) {
                return new Pair<>(sensorId, provider);
            }
        }

        Slog.e(TAG, "Provider not found");
        return null;
    }

第12行,mServiceProviders集合

private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) {
            for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) {
                final Fingerprint21 fingerprint21;
                if ((Build.IS_USERDEBUG || Build.IS_ENG)
                        && getContext().getResources().getBoolean(R.bool.allow_test_udfps)
                        && Settings.Secure.getIntForUser(getContext().getContentResolver(),
                        Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
                        UserHandle.USER_CURRENT) != 0) {
                    fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(),
                            mFingerprintStateCallback, hidlSensor,
                            mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
                } else {
                    fingerprint21 = Fingerprint21.newInstance(getContext(),
                            mFingerprintStateCallback, hidlSensor,
                            mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
                }
                mServiceProviders.add(fingerprint21);
            }
        }

再看看

return provider.second.scheduleAuthenticate 方法调用,实际上就是调用Fingerprint21对象实例。注意 这里的second的用法,可以参照pair使用规则。

继续往下看

@Override
    public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
            int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
            @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
            boolean allowBackgroundAuthentication) {
        mHandler.post(() -> {
            scheduleUpdateActiveUserWithoutHandler(userId);

            final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
            final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
                    mContext, mLazyDaemon, token, requestId, listener, userId, operationId,
                    restricted, opPackageName, cookie, false /* requireConfirmation */,
                    mSensorProperties.sensorId, isStrongBiometric, statsClient,
                    mTaskStackListener, mLockoutTracker,
                    mUdfpsOverlayController, mSidefpsController,
                    allowBackgroundAuthentication, mSensorProperties);
            mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
        });
    }

第17行代码的mScheduler是在这里定义的

public static Fingerprint21 newInstance(@NonNull Context context,
            @NonNull FingerprintStateCallback fingerprintStateCallback,
            @NonNull FingerprintSensorPropertiesInternal sensorProps,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
            @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
        final Handler handler = new Handler(Looper.getMainLooper());
        final BiometricScheduler scheduler =
                new BiometricScheduler(TAG,
                        BiometricScheduler.sensorTypeFromFingerprintProperties(sensorProps),
                        gestureAvailabilityDispatcher);
        final HalResultController controller = new HalResultController(sensorProps.sensorId,
                context, handler,
                scheduler);
        return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler,
                lockoutResetDispatcher, controller);
    }

第7行代码,继续往下看,类BiometricScheduler下寻找方法scheduleClientMonitor

public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor,
            @Nullable BaseClientMonitor.Callback clientCallback) {
        // If the incoming operation should interrupt preceding clients, mark any interruptable
        // pending clients as canceling. Once they reach the head of the queue, the scheduler will
        // send ERROR_CANCELED and skip the operation.
        if (clientMonitor.interruptsPrecedingClients()) {
            for (Operation operation : mPendingOperations) {
                if (operation.mClientMonitor instanceof Interruptable
                        && operation.mState != Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
                    Slog.d(getTag(), "New client incoming, marking pending client as canceling: "
                            + operation.mClientMonitor);
                    operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
                }
            }
        }

        mPendingOperations.add(new Operation(clientMonitor, clientCallback));
        Slog.d(getTag(), "[Added] " + clientMonitor
                + ", new queue size: " + mPendingOperations.size());

        // If the new operation should interrupt preceding clients, and if the current operation is
        // cancellable, start the cancellation process.
        if (clientMonitor.interruptsPrecedingClients()
                && mCurrentOperation != null
                && mCurrentOperation.mClientMonitor instanceof Interruptable
                && mCurrentOperation.mState == Operation.STATE_STARTED) {
            Slog.d(getTag(), "[Cancelling Interruptable]: " + mCurrentOperation);
            cancelInternal(mCurrentOperation);
        }

        startNextOperationIfIdle();
    }

然后来到方法startNextOperationIfIdle

protected void startNextOperationIfIdle() {
        if (mCurrentOperation != null) {
            Slog.v(getTag(), "Not idle, current operation: " + mCurrentOperation);
            return;
        }
        if (mPendingOperations.isEmpty()) {
            Slog.d(getTag(), "No operations, returning to idle");
            return;
        }

        mCurrentOperation = mPendingOperations.poll();
        final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor;
        Slog.d(getTag(), "[Polled] " + mCurrentOperation);

        // If the operation at the front of the queue has been marked for cancellation, send
        // ERROR_CANCELED. No need to start this client.
        if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
            Slog.d(getTag(), "[Now Cancelling] " + mCurrentOperation);
            if (!(currentClient instanceof Interruptable)) {
                throw new IllegalStateException("Mis-implemented client or scheduler, "
                        + "trying to cancel non-interruptable operation: " + mCurrentOperation);
            }

            final Interruptable interruptable = (Interruptable) currentClient;
            interruptable.cancelWithoutStarting(getInternalCallback());
            // Now we wait for the client to send its FinishCallback, which kicks off the next
            // operation.
            return;
        }

        if (mGestureAvailabilityDispatcher != null
                && mCurrentOperation.mClientMonitor instanceof AcquisitionClient) {
            mGestureAvailabilityDispatcher.markSensorActive(
                    mCurrentOperation.mClientMonitor.getSensorId(),
                    true /* active */);
        }

        // Not all operations start immediately. BiometricPrompt waits for its operation
        // to arrive at the head of the queue, before pinging it to start.
        final boolean shouldStartNow = currentClient.getCookie() == 0;
        if (shouldStartNow) {
            if (mCurrentOperation.isUnstartableHalOperation()) {
                final HalClientMonitor<?> halClientMonitor =
                        (HalClientMonitor<?>) mCurrentOperation.mClientMonitor;
                // Note down current length of queue
                final int pendingOperationsLength = mPendingOperations.size();
                final Operation lastOperation = mPendingOperations.peekLast();
                Slog.e(getTag(), "[Unable To Start] " + mCurrentOperation
                        + ". Last pending operation: " + lastOperation);

                // For current operations, 1) unableToStart, which notifies the caller-side, then
                // 2) notify operation's callback, to notify applicable system service that the
                // operation failed.
                halClientMonitor.unableToStart();
                if (mCurrentOperation.mClientCallback != null) {
                    mCurrentOperation.mClientCallback.onClientFinished(
                            mCurrentOperation.mClientMonitor, false /* success */);
                }

                // Then for each operation currently in the pending queue at the time of this
                // failure, do the same as above. Otherwise, it's possible that something like
                // setActiveUser fails, but then authenticate (for the wrong user) is invoked.
                for (int i = 0; i < pendingOperationsLength; i++) {
                    final Operation operation = mPendingOperations.pollFirst();
                    if (operation == null) {
                        Slog.e(getTag(), "Null operation, index: " + i
                                + ", expected length: " + pendingOperationsLength);
                        break;
                    }
                    if (operation.isHalOperation()) {
                        ((HalClientMonitor<?>) operation.mClientMonitor).unableToStart();
                    }
                    if (operation.mClientCallback != null) {
                        operation.mClientCallback.onClientFinished(operation.mClientMonitor,
                                false /* success */);
                    }
                    Slog.w(getTag(), "[Aborted Operation] " + operation);
                }

                // It's possible that during cleanup a new set of operations came in. We can try to
                // run these. A single request from the manager layer to the service layer may
                // actually be multiple operations (i.e. updateActiveUser + authenticate).
                mCurrentOperation = null;
                startNextOperationIfIdle();
            } else {
                Slog.d(getTag(), "[Starting] " + mCurrentOperation);
                currentClient.start(getInternalCallback());
                mCurrentOperation.mState = Operation.STATE_STARTED;
            }
        } else {
            try {
                mBiometricService.onReadyForAuthentication(currentClient.getCookie());
            } catch (RemoteException e) {
                Slog.e(getTag(), "Remote exception when contacting BiometricService", e);
            }
            Slog.d(getTag(), "Waiting for cookie before starting: " + mCurrentOperation);
            mCurrentOperation.mState = Operation.STATE_WAITING_FOR_COOKIE;
        }
    }

见第87行

currentClient.start(getInternalCallback());,这里要分析变量currentClient

//注意这几行代码,是我从源码中挑出来的,非先后顺序关系。

@VisibleForTesting @Nullable Operation mCurrentOperation;

final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor;

mCurrentOperation = mPendingOperations.poll();

mPendingOperations.add(new Operation(clientMonitor, clientCallback));
//这里的mCurrentOperation.mClientMonitor实际上就是 clientMonitor
//可以去方法scheduleClientMonitor中去寻找逻辑,见前面的部分源码
//这里的clientMonitor实际上就是Fingerprint21.scheduleAuthenticate 方法中有定义,在前面有讲解。
//就是如下部分。
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
                    mContext, mLazyDaemon, token, requestId, listener, userId, operationId,
                    restricted, opPackageName, cookie, false /* requireConfirmation */,
                    mSensorProperties.sensorId, isStrongBiometric, statsClient,
                    mTaskStackListener, mLockoutTracker,
                    mUdfpsOverlayController, mSidefpsController,
                    allowBackgroundAuthentication, mSensorProperties);
            mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);

再回到currentClient.start(getInternalCallback());

currentClient 就是对象实例FingerprintAuthenticationClient 

public void start(@NonNull Callback callback) {
        super.start(callback);

        if (mSensorProps.isAnyUdfpsType()) {
            // UDFPS requires user to touch before becoming "active"
            mState = STATE_STARTED_PAUSED;
        } else {
            mState = STATE_STARTED;
        }
    }

第二行,继续往下找AuthenticationClient 类下的start方法

@Override
    public void start(@NonNull Callback callback) {
        super.start(callback);

        final @LockoutTracker.LockoutMode int lockoutMode =
                mLockoutTracker.getLockoutModeForUser(getTargetUserId());
        if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
            Slog.v(TAG, "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
            int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED
                    ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
                    : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
            onError(errorCode, 0 /* vendorCode */);
            return;
        }

        if (mTaskStackListener != null) {
            mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
        }

        Slog.d(TAG, "Requesting auth for " + getOwnerString());

        mStartTimeMs = System.currentTimeMillis();
        mAuthAttempted = true;
        startHalOperation();
    }

见第24行startHalOperation(),实际上就是调用到FingerprintAuthenticationClient  类下的

@Override
    protected void startHalOperation() {
        mSensorOverlays.show(getSensorId(), getShowOverlayReason(), this);

        try {
            // GroupId was never used. In fact, groupId is always the same as userId.
            getFreshDaemon().authenticate(mOperationId, getTargetUserId());
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception when requesting auth", e);
            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
                    0 /* vendorCode */);
            mSensorOverlays.hide(getSensorId());
            mCallback.onClientFinished(this, false /* success */);
        }
    }

getFreshDaemon().authenticate 就是进行指纹服务注册,后面会继续分析相关底层。 

继续往下分析getFreshDaemon()

//HalClientMonitor 文件
getFreshDaemon()

public T getFreshDaemon() {
        //应该调用到Fingerprint21 类下的getDaemon方法
        return mLazyDaemon.getDaemon();
    }

//Fingerprint21 文件
mLazyDaemon = Fingerprint21.this::getDaemon;
@VisibleForTesting
    synchronized IBiometricsFingerprint getDaemon() {
        if (mTestHalEnabled) {
            final TestHal testHal = new TestHal(mContext, mSensorId);
            testHal.setNotify(mHalResultController);
            return testHal;
        }

        if (mDaemon != null) {
            return mDaemon;
        }

        Slog.d(TAG, "Daemon was null, reconnecting, current operation: "
                + mScheduler.getCurrentClient());
        try {
            mDaemon = IBiometricsFingerprint.getService();
        } catch (java.util.NoSuchElementException e) {
            // Service doesn't exist or cannot be opened.
            Slog.w(TAG, "NoSuchElementException", e);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to get fingerprint HAL", e);
        }

        if (mDaemon == null) {
            Slog.w(TAG, "Fingerprint HAL not available");
            return null;
        }

        mDaemon.asBinder().linkToDeath(this, 0 /* flags */);

        // HAL ID for these HIDL versions are only used to determine if callbacks have been
        // successfully set.
        long halId = 0;
        try {
            halId = mDaemon.setNotify(mHalResultController);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to set callback for fingerprint HAL", e);
            mDaemon = null;
        }

        Slog.d(TAG, "Fingerprint HAL ready, HAL ID: " + halId);
        if (halId != 0) {
            scheduleLoadAuthenticatorIds();
            scheduleInternalCleanup(ActivityManager.getCurrentUser(), null /* callback */);
        } else {
            Slog.e(TAG, "Unable to set callback");
            mDaemon = null;
        }

        return mDaemon;
    }

注意第35行,在另外一篇文章 中,会用到

指纹设别流程_liujun3512159的博客-CSDN博客

第16行,mDaemon = IBiometricsFingerprint.getService(),就是hidl调用获取到对应的对象。

IBiometricsFingerprint.getService() 最终的信息在BiometricsFingerprint.cpp中有描述

IBiometricsFingerprint.hal文件如下

/*
 * Copyright (C) 2017 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.hardware.biometrics.fingerprint@2.1;

import IBiometricsFingerprintClientCallback;

interface IBiometricsFingerprint {
  /**
   * Set notification callback:
   * Registers a user function that must receive notifications from the HAL
   * This call must block if the HAL state machine is in busy state until HAL
   * leaves the busy state.
   *
   * @return deviceId is a unique handle for this fingerprint device
   */
  @callflow(next={"setActiveGroup"})
  @entry
  setNotify(IBiometricsFingerprintClientCallback clientCallback)
      generates (uint64_t deviceId);

  /**
   * Fingerprint pre-enroll enroll request:
   * Generates a unique token to upper layers to indicate the start of
   * an enrollment transaction. pre-enroll and post-enroll specify
   * a pin/password cleared time window where enrollment is allowed.
   * Pre-enroll only generates a challenge, a full hardwareAuthToken is
   * generated by trustzone after verifying a pin/password/swipe. This is to
   * ensure adding a new fingerprint template was preceded by some kind of
   * credential confirmation (e.g. device password).
   *
   * @return 0 if function failed, a uint64_t of challenge otherwise.
   */
  @callflow(next={"enroll", "postEnroll"})
  preEnroll() generates (uint64_t authChallenge);

  /**
   * Fingerprint enroll request:
   * Switches the HAL state machine to collect and store a new fingerprint
   * template. Switches back as soon as enroll is complete, signalled by
   * (fingerprintMsg.type == FINGERPRINT_TEMPLATE_ENROLLING &&
   *  fingerprintMsg.data.enroll.samplesRemaining == 0)
   * or after timeoutSec seconds.
   * The fingerprint template must be assigned to the group gid.
   *
   * @param hat a valid Hardware Authentication Token (HAT), generated
   * as a result of a preEnroll() call.
   * @param gid a framework defined fingerprint set (group) id.
   * @param timeoutSec a timeout in seconds.
   *
   * @return debugErrno is a value the framework logs in case it is not 0.
   *
   * A notify() function may be called with a more detailed error structure.
   */
  @callflow(next={"cancel", "enroll", "postEnroll", "remove"})
  enroll(uint8_t[69] hat, uint32_t gid, uint32_t timeoutSec)
      generates (RequestStatus debugErrno);

  /**
   * Finishes the enroll operation and invalidates the preEnroll() generated
   * challenge. This must be called at the end of a multi-finger enrollment
   * session to indicate that no more fingers may be added.
   *
   * @return debugErrno is a value the framework logs in case it is not 0.
   */
  @callflow(next={"authenticate", "setActiveGroup", "enumerate", "remove"})
  postEnroll() generates (RequestStatus debugErrno);

  /**
   * getAuthenticatorId:
   * Returns a token associated with the current fingerprint set. This value
   * must change whenever a new fingerprint is enrolled, thus creating a new
   * fingerprint set.
   *
   * @return getAuthenticatorIdRet current authenticator id, 0 if function
   * failed.
   */
  @callflow(next={"authenticate"})
  getAuthenticatorId() generates (uint64_t AuthenticatorId);

  /**
   * Cancel pending enroll or authenticate, sending FINGERPRINT_ERROR_CANCELED
   * to all running clients. Switches the HAL state machine back to the idle
   * state. Unlike enrollDone() doesn't invalidate the preEnroll() challenge.
   *
   * @return debugErrno is a value the framework logs in case it is not 0.
   */
  @callflow(next={"authenticate", "enroll", "enumerate", "remove",
    "setActiveGroup"})
  cancel() generates (RequestStatus debugErrno);

  /**
   * Enumerate all the fingerprint templates found in the directory set by
   * setActiveGroup():
   * For each template found a notify() must be called with:
   * fingerprintMsg.type == FINGERPRINT_TEMPLATE_ENUMERATED
   * fingerprintMsg.data.enumerated.finger indicating a template id
   * fingerprintMsg.data.enumerated.remainingTemplates indicating how many more
   * enumeration messages to expect.
   *
   * @return debugErrno is a value the framework logs in case it is not 0.
   */
  @callflow(next={"remove", "enroll", "authenticate", "setActiveGroup"})
  enumerate() generates (RequestStatus debugErrno);

  /**
   * Fingerprint remove request:
   * Deletes fingerprint template(s).
   * Works only within the path set by setActiveGroup().
   * For each template found a notify() must be called with:
   * fingerprintMsg.type == FINGERPRINT_TEMPLATE_REMOVED
   * fingerprintMsg.data.removed.finger indicating the template id deleted
   * fingerprintMsg.data.removed.remainingTemplates indicating how many more
   * templates must be deleted by this operation.
   *
   * @param gid group id must match the last group set by setActiveGroup().
   * @param fid template id to delete or 0 to delete all templates within the
   * current group.
   *
   * @return debugErrno is a value the framework logs in case it is not 0.
   */
  @callflow(next={"enumerate", "authenticate", "cancel", "getAuthenticatorId",
    "setActiveGroup"})
  remove(uint32_t gid, uint32_t fid) generates (RequestStatus debugErrno);

  /**
   * Restricts the HAL operation to a set of fingerprints belonging to a group
   * provided. The caller must provide a path to a storage location within the
   * user's data directory.
   *
   * @param gid the fingerprint group (set) id.
   * @param storePath filesystem path to the template storage directory.
   *
   * @return debugErrno is a value the framework logs in case it is not 0.
   */
  @callflow(next={"authenticate", "preEnroll", "enumerate", "remove"})
  setActiveGroup(uint32_t gid, string storePath)
      generates (RequestStatus debugErrno);

  /**
   * Authenticates an operation identified by operationId
   *
   * @param operationId operation id.
   * @param gid fingerprint group id.
   *
   * @return debugErrno is a value the framework logs in case it is not 0.
   */
  @callflow(next={"cancel", "preEnroll", "remove"})
  authenticate(uint64_t operationId, uint32_t gid)
      generates (RequestStatus debugErrno);
};
//BiometricsFingerprint.cpp 文件
BiometricsFingerprint::BiometricsFingerprint() : mClientCallback(nullptr), mDevice(nullptr) {
    sInstance = this; // keep track of the most recent instance
    mDevice = openHal();
    if (!mDevice) {
        ALOGE("Can't open HAL module");
    }
}

见第4行openHal方法

//这个方法最终会访问到底层了,比如我们熟悉的hw_get_module
fingerprint_device_t* BiometricsFingerprint::openHal() {
    int err;
    const hw_module_t *hw_mdl = nullptr;
    ALOGD("Opening fingerprint hal library...");
    if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_mdl))) {
        ALOGE("Can't open fingerprint HW Module, error: %d", err);
        return nullptr;
    }

    if (hw_mdl == nullptr) {
        ALOGE("No valid fingerprint module");
        return nullptr;
    }

    fingerprint_module_t const *module =
        reinterpret_cast<const fingerprint_module_t*>(hw_mdl);
    if (module->common.methods->open == nullptr) {
        ALOGE("No valid open method");
        return nullptr;
    }

    hw_device_t *device = nullptr;

    if (0 != (err = module->common.methods->open(hw_mdl, nullptr, &device))) {
        ALOGE("Can't open fingerprint methods, error: %d", err);
        return nullptr;
    }

    if (kVersion != device->version) {
        // enforce version on new devices because of HIDL@2.1 translation layer
        ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
        return nullptr;
    }

    fingerprint_device_t* fp_device =
        reinterpret_cast<fingerprint_device_t*>(device);

    if (0 != (err =
            fp_device->set_notify(fp_device, BiometricsFingerprint::notify))) {
        ALOGE("Can't register fingerprint module callback, error: %d", err);
        return nullptr;
    }

    return fp_device;
}

第40行,设置回调到底软 ,后面有设置

dev->set_notify = set_notify_callback;

Return<RequestStatus> BiometricsFingerprint::authenticate(uint64_t operationId,
        uint32_t gid) {
    return ErrorFilter(mDevice->authenticate(mDevice, operationId, gid));
}

第25行,module->common.methods->open

全面解析Android系统指纹启动流程_liujun3512159的博客-CSDN博客_android 指纹流程

这个open方法主要是将厂商指纹模组模块的算法识别逻辑结果和HAL层进行绑定(一般是fingerprint.default.so文件),设置回调通知,这个文件一般都不开源,不过Android原生也是有这部分代码的(当然只是看看,并不能使用)

例如,文件Fingerprint.c文件。

static int fingerprint_open(const hw_module_t* module, const char __unused *id,
                            hw_device_t** device)
{
    if (device == NULL) {
        ALOGE("NULL device on open");
        return -EINVAL;
    }

    fingerprint_device_t *dev = malloc(sizeof(fingerprint_device_t));
    memset(dev, 0, sizeof(fingerprint_device_t));

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = FINGERPRINT_MODULE_API_VERSION_2_0;
    dev->common.module = (struct hw_module_t*) module;
    dev->common.close = fingerprint_close;

    dev->pre_enroll = fingerprint_pre_enroll;
    dev->enroll = fingerprint_enroll;
    dev->get_authenticator_id = fingerprint_get_auth_id;
    dev->cancel = fingerprint_cancel;
    dev->remove = fingerprint_remove;
    dev->set_active_group = fingerprint_set_active_group;
    dev->authenticate = fingerprint_authenticate;
    dev->set_notify = set_notify_callback;
    dev->notify = NULL;

    *device = (hw_device_t*) dev;
    return 0;
}

static struct hw_module_methods_t fingerprint_module_methods = {
    .open = fingerprint_open,
};

fingerprint_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag                = HARDWARE_MODULE_TAG,
        .module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,
        .hal_api_version    = HARDWARE_HAL_API_VERSION,
        .id                 = FINGERPRINT_HARDWARE_MODULE_ID,
        .name               = "Demo Fingerprint HAL",
        .author             = "The Android Open Source Project",
        .methods            = &fingerprint_module_methods,
    },
};

好了,指纹服务注册分析到此为止。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/169477.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • ScheduledExecutorService 使用

    ScheduledExecutorService 使用ScheduledExecutorService,我平时没有用过,他的最大优点除了线程池的特性以外,可以实现循环或延迟任务。ScheduledExecutorService,是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。需要注意,只有当调度任务来的时候,ScheduledExecutorService才会真正启动一个线程,其余时间ScheduledExecutorService都是出于轮询任务的状态。先来个简单的延迟任务调…

  • SKISTYLE_flask-caching

    SKISTYLE_flask-caching关于sklearn.model_selected中的KFold.split的理解作用:返回样本切分之后数据集的indices,即索引返回:train:ndarray。如果KFold设置shuffle参数是True,是混乱的。test:ndarray。如果KFold设置shuffle参数是True/False,是按照顺序连续!!示例ab_range=np.array(range(0,100)…

  • MySQL与PostgreSQL相比哪个更好?

    MySQL与PostgreSQL相比哪个更好?

  • Spring Boot 2 学习笔记(1 / 2)[通俗易懂]

    Spring Boot 2 学习笔记(1 / 2)[通俗易懂]01、基础入门-SpringBoot2课程介绍SpringBoot2核心技术SpringBoot2响应式编程学习要求-熟悉Spring基础-熟悉Maven使用环境要求Java8及以上Maven3.3及以上学习资料SpringBoot官网SpringBoot官方文档本课程文档地址视频地址1、视频地址2源码地址02、基础入门-Spring生态圈Spring官网Spring能做什么Spring的能力Spring的生态覆盖了:w

  • javascript简介_javascript对象

    javascript简介_javascript对象JavaScript中ActiveXObject对象是启用并返回Automation对象的引用。使用方法:newObj=newActiveXObject(servername.typename[,location])ActiveXObject对象语法有这些部分:其中newObj是必选项。要赋值为ActiveXObject的变量名。servername是必选项。提供

    2022年10月14日
  • Android preference_android studio preview

    Android preference_android studio preview以前我们经常使用PreferenceActivity来显示给用户一个选项设置的界面,而现在Google推荐用PreferenceFragment来代替使用.先来看看官方文档的描述:Thepreferencehierarchycanbeformedinmultipleways:FromanXMLfilespecifyingthehierarchyFro

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号