乐趣区

Android-10-核心服务-系列-Fingerprint-Enroll-流程

前言

因为源码剖析的代码量比拟大,大部分博客网站的内容显示页面都比拟窄,显示进去的成果都异样俊俏,所以您也能够间接查看《Thinking in Android》来浏览这边文章,心愿这篇文章能帮你梳理分明 “指纹注册流程”

外围源码

要害类 门路
FingerprintEnrollIntroduction.java packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
BiometricEnrollIntroduction.java packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
FingerprintEnrollEnrolling.java packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
BiometricsEnrollEnrolling.java packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
FingerprintEnrollSidecar.java packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
BiometricEnrollSidecar.java packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollSidecar.java
FingerprintEnrollFindSensor.java packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
FingerprintManager.java frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java
FingerprintService.java frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
BiometricServiceBase.java frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
EnrollClient.java frameworks/base/services/core/java/com/android/server/biometrics/EnrollClient.java

相干类

要害类 阐明
BiometricEnrollBase 指纹录制的基类。
FingerprintEnrollFindSensor 指纹开始筹备录入的 Activity,继承 BiometricEnrollBase
FingerprintEnrollSidecar 注册 EnrollmentCallback,监听指纹录入状态,继承 BiometricEnrollSidecar
FingerprintEnrollEnrolling 指纹录入过程的 Activity,继承 BiometricEnrollBase 类。
FingerprintEnrollFinish 指纹录制完结后调用的 Activity,继承 BiometricEnrollBase 类。
FingerprintRemoveSidecar 治理指纹删除操作。
FingerprintFindSensorAnimation 指纹动画接口。
FingerprintLocationAnimationView 指纹动画,实现了 FingerprintFindSensorAnimation 接口。

本篇文章,咱们从源码角度探讨指纹录入的过程(测试样机:Pixel),咱们先看下 UI 图,这个你应该不生疏了。

一、FingerprintEnrollIntroduction

接下来咱们就从指纹疏导界面开始源码剖析,图 1 的逻辑就在 FingerprintEnrollIntroduction 类,点击 Next 执行下一步,会执行 onNextButtonClick() 办法。

1.1 FingerprintEnrollIntroduction.onNextButtonClick()

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java

public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        mFingerprintManager = Utils.getFingerprintManagerOrNull(this);

        mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
        
        // Cancel Button
        mFooterBarMixin.setSecondaryButton(new FooterButton.Builder(this)
                        .setText(R.string.security_settings_face_enroll_introduction_cancel)
                        .setListener(this::onCancelButtonClick)
                        .setButtonType(FooterButton.ButtonType.SKIP)
                        .setTheme(R.style.SudGlifButton_Secondary)
                        .build());

        // Next Button
        mFooterBarMixin.setPrimaryButton(new FooterButton.Builder(this)
                        .setText(R.string.wizard_next)
                        .setListener(this::onNextButtonClick)    // 点击 "下一步" 的解决流程
                        .setButtonType(FooterButton.ButtonType.NEXT)
                        .setTheme(R.style.SudGlifButton_Primary)
                        .build());
    }

}

咱们能够发现:FingerprintEnrollIntroduction 继承自 BiometricEnrollIntroductiononNextButtonClick() 办法在其父类 BiometricEnrollIntroduction 中解决。

二、BiometricEnrollIntroduction

2.1 BiometricEnrollIntroduction.onNextButtonClick()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java

public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
        implements LinkSpan.OnClickListener {

    @Override
    protected void onNextButtonClick(View view) {
        mNextClicked = true;
        if (checkMaxEnrolled() == 0) {
            // Lock thingy is already set up, launch directly to the next page
            launchNextEnrollingActivity(mToken);    // 接下来就要拉起指纹录入界面
        } else {setResult(RESULT_FINISHED);
            finish();}
    }
        
}

2.2 BiometricEnrollIntroduction.launchNextEnrollingActivity()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java

public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
        implements LinkSpan.OnClickListener {private void launchNextEnrollingActivity(byte[] token) {Intent intent = getEnrollingIntent();    // 获取 FingerprintEnrollFindSensor
        if (token != null) {intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
        }
        if (mUserId != UserHandle.USER_NULL) {intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
        }
        intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
        startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);    // 跳转 FingerprintEnrollFindSensor
    }
        
}

咱们看下 getEnrollingIntent() 办法:

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java

public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
        implements LinkSpan.OnClickListener {protected abstract Intent getEnrollingIntent();    // 形象办法,由子类 FingerprintEnrollIntroduction 实现
    
}

所以咱们跳转到 FingerprintEnrollIntroduction

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java

public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {

    @Override
    protected Intent getEnrollingIntent() {return new Intent(this, FingerprintEnrollFindSensor.class);    // 获取 FingerprintEnrollFindSensor
    }
    
}

三、FingerprintEnrollFindSensor

咱们把下面的图再拿过去,此时就进入了图 2 界面的逻辑,咱们接着往下看。

3.1 FingerprintEnrollFindSensor.onCreate()

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java

public class FingerprintEnrollFindSensor extends BiometricEnrollBase {

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(getContentView());
        mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
        // Skip button
        mFooterBarMixin.setSecondaryButton(new FooterButton.Builder(this)
                        .setText(R.string.skip_label)
                        .setListener(this::onSkipButtonClick)
                        .setButtonType(FooterButton.ButtonType.SKIP)
                        .setTheme(R.style.SudGlifButton_Secondary)
                        .build());

        // Touch the sensor
        setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);

        // 执行 startLookingForFingerprint() 办法
        startLookingForFingerprint(); // already confirmed, so start looking for fingerprint

        // 演示动画
        View animationView = findViewById(R.id.fingerprint_sensor_location_animation);
        if (animationView instanceof FingerprintFindSensorAnimation) {mAnimation = (FingerprintFindSensorAnimation) animationView;
        } else {mAnimation = null;}
    }

}

到这里都只是波及到 UI 界面的相干逻辑,接下来的代码逻辑就略微简单一点了,咱们认真深挖钻研。

3.2 FingerprintEnrollFindSensor.startLookingForFingerprint()

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java

public class FingerprintEnrollFindSensor extends BiometricEnrollBase {

    private FingerprintEnrollSidecar mSidecar;
    private boolean mNextClicked;

    private void startLookingForFingerprint() {
        // FingerprintEnrollSidecar 这个 fragment 的生命周期正式开启
        mSidecar = (FingerprintEnrollSidecar) getSupportFragmentManager().findFragmentByTag(FingerprintEnrollEnrolling.TAG_SIDECAR);
        if (mSidecar == null) {mSidecar = new FingerprintEnrollSidecar();
            // 增加 FingerprintEnrollEnrolling
            getSupportFragmentManager().beginTransaction()
                    .add(mSidecar, FingerprintEnrollEnrolling.TAG_SIDECAR)
                    .commitAllowingStateLoss();}

        // FingerprintEnrollEnrolling 实现了 BiometricEnrollSidecar.Listener 接口
        mSidecar.setListener(new Listener() {    // 匿名外部类的形式实现接口办法
            @Override
            public void onEnrollmentProgressChange(int steps, int remaining) {
                mNextClicked = true;
                proceedToEnrolling(true /* cancelEnrollment */);
            }

            @Override
            public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }

            @Override
            public void onEnrollmentError(int errMsgId, CharSequence errString) {if (mNextClicked && errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
                    mNextClicked = false;
                    proceedToEnrolling(false /* cancelEnrollment */);
                }
            }
        });
    }

}

这外面有个重点办法:onEnrollmentProgressChange(),如果咱们此时用手指贴在指纹传感器上,会产生反馈信息的回调,此时 onEnrollmentProgressChange() 办法被执行,进入执行 proceedToEnrolling() 办法,咱们看下这个办法:

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java

public class FingerprintEnrollFindSensor extends BiometricEnrollBase {private void proceedToEnrolling(boolean cancelEnrollment) {if (mSidecar != null) {if (cancelEnrollment) {if (mSidecar.cancelEnrollment()) {
                    // Enrollment cancel requested. When the cancellation is successful,
                    // onEnrollmentError will be called with FINGERPRINT_ERROR_CANCELED, calling
                    // this again.
                    return;
                }
            }
            getSupportFragmentManager().beginTransaction().remove(mSidecar).
                    commitAllowingStateLoss();
            mSidecar = null;
            // getFingerprintEnrollingIntent() 办法会返回一个蕴含 FingerprintEnrollEnrolling 的 Intent
            startActivityForResult(getFingerprintEnrollingIntent(), ENROLL_REQUEST);
        }
    }

}

失常流程会走到 startActivityForResult() 办法,跳转到 FingerprintEnrollEnrolling 界面。

四、FingerprintEnrollEnrolling

咱们把下面的图再拿过去,此时就进入了图 3 界面的逻辑,咱们接着往下看。

4.1 FingerprintEnrollEnrolling.onStart()

咱们重点关注 onStart() 办法:

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java

/**
 * Activity which handles the actual enrolling for fingerprint.
 */
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {

    @Override
    protected void onStart() {super.onStart();    // 调用父类 BiometricEnrollSidecar 的 onStart() 办法
        updateProgress(false /* animate */);    // 更新录入进度
        updateDescription();
        if (mRestoring) {startIconAnimation();
        }
    }

}

FingerprintEnrollEnrolling 类继承自 BiometricsEnrollEnrolling 类,而 BiometricsEnrollEnrolling 类实现了 BiometricEnrollSidecar.Listener 接口,所以 FingerprintEnrollEnrolling 也实现了 BiometricEnrollSidecar.Listener 接口。

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java

/**
 * Activity which handles the actual enrolling for fingerprint.
 */
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {

    // 指纹录制时提醒(比方太快,挪动手指之类)@Override
    public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {if (!TextUtils.isEmpty(helpString)) {mErrorText.removeCallbacks(mTouchAgainRunnable);
            showError(helpString);
        }
    }

    // 提醒指纹录制过程中超时,或者未注册
    @Override
    public void onEnrollmentError(int errMsgId, CharSequence errString) {
        int msgId;
        switch (errMsgId) {
            case FingerprintManager.FINGERPRINT_ERROR_TIMEOUT:
                msgId = R.string.security_settings_fingerprint_enroll_error_timeout_dialog_message;
                break;
            default:
                msgId = R.string.security_settings_fingerprint_enroll_error_generic_dialog_message;
                break;
        }
        showErrorDialog(getText(msgId), errMsgId);
        stopIconAnimation();
        mErrorText.removeCallbacks(mTouchAgainRunnable);
    }

    // 录制过程中进度的变动(手指按压指纹传感区,onEnrollmentProgressChange() 会被触发,执行一系列解决工作)@Override
    public void onEnrollmentProgressChange(int steps, int remaining) {updateProgress(true /* animate */);    // 更新进度
        updateDescription();    // 更新形容
        clearError();
        animateFlash();    // 更新动画
        mErrorText.removeCallbacks(mTouchAgainRunnable);
        mErrorText.postDelayed(mTouchAgainRunnable, HINT_TIMEOUT_DURATION);
    }

}

五、BiometricsEnrollEnrolling

5.1 BiometricsEnrollEnrolling.onStart()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java

public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
        implements BiometricEnrollSidecar.Listener {

    @Override
    protected void onStart() {super.onStart();
        if (shouldStartAutomatically()) {    // 恒定为 true
            startEnrollment();    // 调用 startEnrollment() 办法
        }
    }
        
}

5.2 BiometricsEnrollEnrolling.startEnrollment()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java

public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
        implements BiometricEnrollSidecar.Listener {

    protected BiometricEnrollSidecar mSidecar;

    protected abstract BiometricEnrollSidecar getSidecar();    // 形象办法,由子类实现

    public void startEnrollment() {// 调用 BiometricEnrollSidecar 的 onStart() 办法
        mSidecar = (BiometricEnrollSidecar) getSupportFragmentManager()
                .findFragmentByTag(TAG_SIDECAR);
        if (mSidecar == null) {mSidecar = getSidecar();    // 获取 mSidecar
            getSupportFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR)
                    .commitAllowingStateLoss();}
        mSidecar.setListener(this);
    }
        
}

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java

public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {

    @Override
    protected BiometricEnrollSidecar getSidecar() {
        // 返回了一个继承自 BiometricEnrollSidecar 的 FingerprintEnrollSidecar 对象
        return new FingerprintEnrollSidecar();}

}

六、FingerprintEnrollSidecar

6.1 FingerprintEnrollSidecar.startEnrollment()

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java

/**
 * Sidecar fragment to handle the state around fingerprint enrollment.
 */
public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {

    private FingerprintManager mFingerprintManager;

    @Override
    protected void startEnrollment() {super.startEnrollment();
        if (mUserId != UserHandle.USER_NULL) {mFingerprintManager.setActiveUser(mUserId);
        }
        /*
         * 调用 FingeprintManager 的 enroll() 办法开始录入,并且传入了 EnrollmentCallback 对象
         * EnrollmentCallback 是指纹录入后果的回调,别离调用了 BiometricEnrollSidecar.Listener 接口中的办法,* 这样就能更新指纹录制的进度和录制后果。*/
        mFingerprintManager.enroll(mToken, mEnrollmentCancel, 0 /* flags */, mUserId, mEnrollmentCallback);
    }

咱们看下 EnrollmentCallback 对象是什么:

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java

public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {

    private FingerprintManager.EnrollmentCallback mEnrollmentCallback
            = new FingerprintManager.EnrollmentCallback() {

        @Override
        public void onEnrollmentProgress(int remaining) {FingerprintEnrollSidecar.super.onEnrollmentProgress(remaining);
        }

        @Override
        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {FingerprintEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);
        }

        @Override
        public void onEnrollmentError(int errMsgId, CharSequence errString) {FingerprintEnrollSidecar.super.onEnrollmentError(errMsgId, errString);
        }
    };

}

七、FingerprintManager

7.1 FingerprintManager.enroll()

// frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java

public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {

    private IFingerprintService mService;

    // CancellationSignal 类提供删除信号类,提供终止操作的能力
    @RequiresPermission(MANAGE_FINGERPRINT)
    public void enroll(byte [] token, CancellationSignal cancel, int flags,
            int userId, EnrollmentCallback callback) {if (userId == UserHandle.USER_CURRENT) {userId = getCurrentUserId();
        }
        if (callback == null) {throw new IllegalArgumentException("Must supply an enrollment callback");
        }

        if (cancel != null) {if (cancel.isCanceled()) {Slog.w(TAG, "enrollment already canceled");
                return;
            } else {cancel.setOnCancelListener(new OnEnrollCancelListener());
            }
        }

        if (mService != null) try {
            mEnrollmentCallback = callback;
            // 调用 FingerprintServiceWrapper 的 enroll() 办法
            mService.enroll(mToken, token, userId, mServiceReceiver, flags,
                    mContext.getOpPackageName());
        } catch (RemoteException e) {Slog.w(TAG, "Remote exception in enroll:", e);
            if (callback != null) {
                // Though this may not be a hardware issue, it will cause apps to give up or try
                // again later.
                callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
                        getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
                            0 /* vendorCode */));
            }
        }
    }

}

八、FingerprintService

8.1 FingerprintServiceWrapper.enroll()

FingerprintManagerFingerprintService 间接通过 aidl 进行通信,在 FingerprintService 中外部类 FingerprintServiceWrapper 实现了 IFingerprintService.Stub,咱们调用的 FingerMangerenroll() 办法就是调用 FingerprintServiceWrapper 类中的 enroll() 办法。

// frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java

public class FingerprintService extends BiometricServiceBase {

    /**
     * Receives the incoming binder calls from FingerprintManager.
     */
    private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
    
        @Override // Binder call
        public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
                final IFingerprintServiceReceiver receiver, final int flags,
                final String opPackageName) {checkPermission(MANAGE_FINGERPRINT);

            final boolean restricted = isRestricted();
            final int groupId = userId; // default group for fingerprint enrollment
            final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,
                    mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, groupId,
                    cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */,
                    ENROLL_TIMEOUT_SEC) {
                @Override
                public boolean shouldVibrate() {return true;}

                @Override
                protected int statsModality() {return FingerprintService.this.statsModality();
                }
            };

            enrollInternal(client, userId);    // 调用 BiometricServiceBase 的 enrollInternal() 办法}

    }

}

九、BiometricServiceBase

9.1 BiometricServiceBase.enrollInternal()

// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

public abstract class BiometricServiceBase extends SystemService
        implements IHwBinder.DeathRecipient {protected void enrollInternal(EnrollClientImpl client, int userId) {if (hasReachedEnrollmentLimit(userId)) {return;}

        // Group ID is arbitrarily set to parent profile user ID. It just represents
        // the default biometrics for the user.
        if (!isCurrentUserOrProfile(userId)) {return;}

        mHandler.post(() -> {startClient(client, true /* initiatedByClient */);    // 调用 startClient() 办法});
    }        

}

9.2 BiometricServiceBase.startClient()

// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

public abstract class BiometricServiceBase extends SystemService
        implements IHwBinder.DeathRecipient {private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
        ClientMonitor currentClient = mCurrentClient;
        if (currentClient != null) {if (DEBUG) Slog.v(getTag(), "request stop current client" +
                    currentClient.getOwnerString());
            if (currentClient instanceof InternalEnumerateClient
                    || currentClient instanceof InternalRemovalClient) {if (newClient != null) {Slog.w(getTag(), "Internal cleanup in progress but trying to start client"
                            + newClient.getClass().getSuperclass().getSimpleName()
                            + "(" + newClient.getOwnerString() + ")"
                            + ", initiatedByClient =" + initiatedByClient);
                }
            } else {currentClient.stop(initiatedByClient);

                mHandler.removeCallbacks(mResetClientState);
                mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
            }
            mPendingClient = newClient;
        } else if (newClient != null) {if (newClient instanceof AuthenticationClient) {AuthenticationClient client = (AuthenticationClient) newClient;
                if (client.isBiometricPrompt()) {if (DEBUG) Slog.v(getTag(), "Returning cookie:" + client.getCookie());
                    mCurrentClient = newClient;
                    if (mBiometricService == null) {
                        mBiometricService = IBiometricService.Stub.asInterface(ServiceManager.getService(Context.BIOMETRIC_SERVICE));
                    }
                    try {mBiometricService.onReadyForAuthentication(client.getCookie(),
                                client.getRequireConfirmation(), client.getTargetUserId());
                    } catch (RemoteException e) {Slog.e(getTag(), "Remote exception", e);
                    }
                    return;
                }
            }

            // We are not a BiometricPrompt client, start the client immediately
            mCurrentClient = newClient;
            startCurrentClient(mCurrentClient.getCookie());    // 调用 startCurrentClient() 办法}
    }
        
}

9.3 BiometricServiceBase.startCurrentClient()

// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

public abstract class BiometricServiceBase extends SystemService
        implements IHwBinder.DeathRecipient {

    private ClientMonitor mCurrentClient;

    protected void startCurrentClient(int cookie) {if (mCurrentClient == null) {Slog.e(getTag(), "Trying to start null client!");
            return;
        }
        if (DEBUG) Slog.v(getTag(), "starting client"
                + mCurrentClient.getClass().getSuperclass().getSimpleName()
                + "(" + mCurrentClient.getOwnerString() + ")"
                + "targetUserId:" + mCurrentClient.getTargetUserId()
                + "currentUserId:" + mCurrentUserId
                + "cookie:" + cookie + "/" + mCurrentClient.getCookie());
        if (cookie != mCurrentClient.getCookie()) {Slog.e(getTag(), "Mismatched cookie");
            return;
        }
        notifyClientActiveCallbacks(true);
        mCurrentClient.start();    // 调用 EnrollClient 的 start() 办法
    }

}

十、EnrollClient

10.1 EnrollClient.start()

// frameworks/base/services/core/java/com/android/server/biometrics/EnrollClient.java

// EnrollClient 是为给定的客户端跟踪指纹录制状态
public abstract class EnrollClient extends ClientMonitor {

    // start 办法会调用 fingerprintd,调用底层的指纹库,底层库返回后果后会调用 onEnrollResult 来反馈后果给 receiver,再往下层反馈。@Override
    public int start() {mEnrollmentStartTimeMs = System.currentTimeMillis();
        try {final ArrayList<Integer> disabledFeatures = new ArrayList<>();
            for (int i = 0; i < mDisabledFeatures.length; i++) {disabledFeatures.add(mDisabledFeatures[i]);
            }

            final int result = getDaemonWrapper().enroll(mCryptoToken, getGroupId(), mTimeoutSec,
                    disabledFeatures);
            if (result != 0) {Slog.w(getLogTag(), "startEnroll failed, result=" + result);
                mMetricsLogger.histogram(mConstants.tagEnrollStartError(), result);
                onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
                        0 /* vendorCode */);
                return result;
            }
        } catch (RemoteException e) {Slog.e(getLogTag(), "startEnroll failed", e);
        }
        return 0; // success
    }

}

getDaemonWrapper().enroll() 会调用 fingerprintd,调用底层的指纹库,底层库返回后果后会调用 onEnrollResult 来反馈后果给 receiver,在往下层反馈。这就是指纹的录制流程。

// frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java

public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {

    private Handler mHandler;

    // mServiceReceiver 对象会通过 handler 发送相干音讯去调用 EnrollmentCallback 或者 AuthenticationCallback 中办法
    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {

        @Override // binder call
        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();}

        @Override // binder call
        public void onAcquired(long deviceId, int acquireInfo, int vendorCode) {
            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode,
                    deviceId).sendToTarget();}

        @Override // binder call
        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();}

        @Override // binder call
        public void onAuthenticationFailed(long deviceId) {mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();}

        @Override // binder call
        public void onError(long deviceId, int error, int vendorCode) {mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();}

        @Override // binder call
        public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
            mHandler.obtainMessage(MSG_REMOVED, remaining, 0,
                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();}

        @Override // binder call
        public void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {
            // TODO: propagate remaining
            mHandler.obtainMessage(MSG_ENUMERATED, fingerId, groupId, deviceId).sendToTarget();}
    };
    
    private class MyHandler extends Handler {private MyHandler(Context context) {super(context.getMainLooper());
        }

        private MyHandler(Looper looper) {super(looper);
        }

        @Override
        public void handleMessage(android.os.Message msg) {switch (msg.what) {
                case MSG_ENROLL_RESULT:
                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
                    break;
                case MSG_ACQUIRED:
                    sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */,
                            msg.arg2 /* vendorCode */);
                    break;
                case MSG_AUTHENTICATION_SUCCEEDED:
                    sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
                    break;
                case MSG_AUTHENTICATION_FAILED:
                    sendAuthenticatedFailed();
                    break;
                case MSG_ERROR:
                    sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */,
                            msg.arg2 /* vendorCode */);
                    break;
                case MSG_REMOVED:
                    sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
                    break;
                case MSG_ENUMERATED:
                    sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
                            msg.arg2 /* groupId */);
                    break;
            }
        }
    };
}

看下 MSG_ENROLL_RESULT

// frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java

public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {private void sendEnrollResult(Fingerprint fp, int remaining) {if (mEnrollmentCallback != null) {
            // 调用 EnrollmentCallback 的 onEnrollmentProgress 办法
            mEnrollmentCallback.onEnrollmentProgress(remaining);
        }
    }

}

退出移动版