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

生物识别指纹_生物指纹识别技术锁屏要使用指纹解锁,首先要注册指纹服务,我看过的一些大厂项目中,实际上是在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)


相关推荐

  • linux部署tomact不能打开页面的情况

    linux部署tomact不能打开页面的情况

  • dubbo如何实现rpc调用_dubbo支持grpc

    dubbo如何实现rpc调用_dubbo支持grpc使用telnet测试dubborpc接口

  • docker 搭建drone + gitee 的CI/CD

    docker 搭建drone + gitee 的CI/CD准备创建OAuth应用程序创建一个GiteeOAuth应用程序。ConsumerKey和ConsumerSecret用于授权访问Gitee资源。授权回调URL必须与以下格式和路径匹配,并且必须使用您的确切服务器方案和主机。创建共享密钥创建一个共享密钥来验证跑步者和您的中央无人机服务器之间的通信。您可以使用openssl生成共享密钥:$opensslrand-hex16bea26a2221fd8090ea38720fc445ec.

  • 内存屏障 – MemoryBarrier[通俗易懂]

    内存屏障 – MemoryBarrier[通俗易懂]处理器的乱序和并发执行目前的高级处理器,为了提高内部逻辑元件的利用率以提高运行速度,通常会采用多指令发射、乱序执行等各种措施。现在普遍使用的一些超标量处理器通常能够在一个指令周期内并发执行多条指令。处理器从L1I-Cache预取了一批指令后,就会分析找出那些互相没有关联可以并发执行的指令,然后送到几个独立的执行单元进行并发执行。比如下面这样的代码(假定编译器不做优化):  z

  • matlab画图常用符号,matlab画图特殊符号[通俗易懂]

    matlab画图常用符号,matlab画图特殊符号[通俗易懂]在MATLAB中使用LaTex字符1.Tex字符表在text对象的函数中(函数title、xlabel、ylabel、zlabel或text),说明文字除使用标准的ASCII字符外,还可……matlab特殊字符_工学_高等教育_教育专区。本文说明了matlab中如何输入特殊字符,如希腊字母字符映射表C:\\WINDOWS\\system32\\charmap….

  • 查看linux执行的命令记录_history命令用法

    查看linux执行的命令记录_history命令用法前言我们每次敲打linux命令的时候,有时候想用之前用过的命令,一般情况下,我们都会按↑↓箭头来寻找历史的命令记录,那如果我想用1天前执行的某条命令,难道还要按↑100次?显示这样是不现实的,我们可

发表回复

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

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