BiometricPrompt之七 - Android R AuthBiometricView BiometricDialogView无法消失解决方案

Android R于近期发布,针对Android Q BiometricPrompt暴露的一些bug,R中给出了答案。
一起来看看吧

之前我们已经报了BiometricPrompt于Android Q的重要bug,见《BiometricPrompt之四 - BiometricDialogView无法消失》

 

首先看视频:

Biomtric AuthBiometricView
Biometic AuthBiometricView

再看看android R log:

04-18 12:47:53.832   914   914 D BiometricService: Package: com.android.settings Authenticator ID: 0 Modality: 2 Reported Modality: 2 Status: 1
04-18 12:47:53.832   914   914 D BiometricService: Creating auth session. Modality: 2, cookie: 847382688, authenticators: 33023
04-18 12:47:53.836   914   914 V FingerprintService: startAuthentication(com.android.settings)
04-18 12:47:53.836   914   914 V FingerprintService: Returning cookie: 847382688
04-18 12:47:53.837   914   914 D BiometricService: Matched cookie: 847382688, 0 remaining
04-18 12:47:53.837   914   914 V FingerprintService: starting client AuthenticationClientImpl(com.android.settings) targetUserId: 0 currentUserId: 0 cookie: 847382688/847382688
04-18 12:47:53.837   755   861 D android.hardware.biometrics.fingerprint@2.1-service: BiometricsFingerprint::authenticate(opid, gid)
04-18 12:47:53.965   914   914 W FingerprintService: client com.android.settings is authenticating...
04-18 12:47:53.966   914   914 W Looper  : Slow dispatch took 130ms main h=com.android.server.biometrics.BiometricService$1 c=null m=8
04-18 12:47:53.968  2569  2569 D BiometricPrompt/AuthController: showAuthenticationDialog, authenticators: 33023, biometricModality: 2, requireConfirmation: false, operationId: 0
04-18 12:47:53.985  2569  2569 D BiometricPrompt/AuthController: userId: 0 savedState: null mCurrentDialog: null newDialog: com.android.systemui.biometrics.AuthContainerView{5905139 VFE...... .F....I. 0,0-0,0} type: 2
04-18 12:47:54.007  2569  2569 V BiometricPrompt/AuthBiometricView: newState: 1
04-18 12:47:54.019  2569  2569 V BiometricPrompt/AuthBiometricView: Current size: 0 New size: 2
04-18 12:47:54.026   604  2071 E BufferQueueCore: [BiometricPrompt#0](id:25c00000047,api:1,p:2569,c:604) Slot 1 is in mActiveBuffers but has no buffer
04-18 12:47:54.303  2569  2569 V BiometricPrompt/AuthBiometricView: newState: 2
//Menu pressed
04-18 12:48:13.855  2569  2569 W BiometricPrompt/AuthController: ACTION_CLOSE_SYSTEM_DIALOGS received
04-18 12:48:13.865   914   914 V FingerprintService: Stopping client com.android.settings, fromClient: false
04-18 12:48:13.976   755   861 D android.hardware.biometrics.fingerprint@2.1-service: onError(5)
04-18 12:48:13.977   914   914 W FingerprintService: client com.android.settings is no longer authenticating
04-18 12:48:13.977   914   914 W Looper  : Slow dispatch took 113ms main h=com.android.server.biometrics.BiometricServiceBase$H c=com.android.server.biometrics.-$$Lambda$BiometricServiceBase$B1PDNz5plOtQUbeZgXMkI_dh_yQ@5ebc01d m=0
04-18 12:48:13.977   914   914 V FingerprintService: handleError(client=com.android.settings, error = 5)
04-18 12:48:13.977   914   914 V BiometricStats: Error latency: -1
04-18 12:48:13.977   914   914 W BiometricStats: found a negative latency : -1
04-18 12:48:13.978   914   914 V FingerprintService: Done with client: com.android.settings
04-18 12:48:13.978   914   914 D BiometricService: handleOnError: 5 cookie: 847382688
04-18 12:48:13.979   914   914 E BiometricService: Unknown cookie: 847382688
04-18 12:48:14.244  2569  2569 D BiometricPrompt/AuthContainerView: pendingCallback: null
04-18 12:48:14.296   914  1016 W InputDispatcher: channel '18f1ba9 BiometricPrompt (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
04-18 12:48:14.296   914  1016 E InputDispatcher: channel '18f1ba9 BiometricPrompt (server)' ~ Channel is unrecoverably broken and will be disposed!
04-18 12:48:14.306   914  1663 W InputDispatcher: Attempted to unregister already unregistered input channel '18f1ba9 BiometricPrompt (server)'

指纹验证成功的log:

指纹验证成功的log:
04-18 12:47:48.626   755   907 D android.hardware.biometrics.fingerprint@2.1-service: onAcquired(0)
04-18 12:47:48.626   755   907 D android.hardware.biometrics.fingerprint@2.1-service: onAcquired(6)
04-18 12:47:48.628   914   914 V FingerprintService: Acquired: 0 0
04-18 12:47:48.633   914   914 V FingerprintService: Acquired: 6 2
04-18 12:47:48.634   914   914 W FingerprintManager: Invalid acquired message: 6, 2
04-18 12:47:48.634   914   914 W BiometricService: Ignoring null message: 0
04-18 12:47:48.635   914   914 W BiometricService: Ignoring null message: 6
04-18 12:47:48.700   755   907 D android.hardware.biometrics.fingerprint@2.1-service: onAcquired(0)
04-18 12:47:48.700   755   907 D android.hardware.biometrics.fingerprint@2.1-service: onAuthenticated(fid=1153064581, gid=0)
04-18 12:47:48.701   914   914 V FingerprintService: Acquired: 0 0
04-18 12:47:48.702   914   914 V BiometricStats: Authentication latency: -1
04-18 12:47:48.702   914   914 W BiometricStats: found a negative latency : -1
04-18 12:47:48.703   914   914 V FingerprintService: onAuthenticated(true), ID:1153064581, Owner: com.android.settings, isBP: true, listener: com.android.server.biometrics.fingerprint.FingerprintService$BiometricPromptServiceListenerImpl@4317d4, requireConfirmation: false, user: 0
04-18 12:47:48.709   914   914 V FingerprintService: Done with client: com.android.settings
04-18 12:47:48.709   914   914 W BiometricService: Ignoring null message: 0
04-18 12:47:48.715  2569  2569 V BiometricPrompt/AuthBiometricView: newState: 6
04-18 12:47:48.767   755   907 I chatty  : uid=1000(system) fingerprint@2.1 identical 1 line
04-18 12:47:48.948   755   907 D android.hardware.biometrics.fingerprint@2.1-service: onAcquired(6)
04-18 12:47:49.116  2569  2569 D BiometricPrompt/AuthContainerView: pendingCallback: 4
04-18 12:47:49.117  2569  2569 D BiometricPrompt/AuthController: onDialogDismissed: 4
04-18 12:47:49.146   914  1016 W InputDispatcher: channel '68b0a19 BiometricPrompt (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
04-18 12:47:49.146   914  1016 E InputDispatcher: channel '68b0a19 BiometricPrompt (server)' ~ Channel is unrecoverably broken and will be disposed!
04-18 12:47:49.146   914  2439 W InputDispatcher: Attempted to unregister already unregistered input channel '68b0a19 BiometricPrompt (server)'

 


再看看源码:

lenovo@HZCS13:~/coding/r/frameworks/base/packages/SystemUI$ ll src/com/android/systemui/biometrics/
total 164
drwxr-xr-x  2 lenovo lenov  4096 Apr 18 18:18 ./
drwxr-xr-x 49 lenovo lenov  4096 Apr 18 18:18 ../
-rw-r--r--  1 lenovo lenov  8325 Apr 18 18:18 AuthBiometricFaceView.java
-rw-r--r--  1 lenovo lenov  4453 Apr 18 18:18 AuthBiometricFingerprintView.java
-rw-r--r--  1 lenovo lenov 29073 Apr 18 18:18 AuthBiometricView.java
-rw-r--r--  1 lenovo lenov 23530 Apr 18 18:18 AuthContainerView.java
-rw-r--r--  1 lenovo lenov 18094 Apr 18 18:18 AuthController.java
-rw-r--r--  1 lenovo lenov  4519 Apr 18 18:18 AuthCredentialPasswordView.java
-rw-r--r--  1 lenovo lenov  3483 Apr 18 18:18 AuthCredentialPatternView.java
-rw-r--r--  1 lenovo lenov 18594 Apr 18 18:18 AuthCredentialView.java
-rw-r--r--  1 lenovo lenov  2219 Apr 18 18:18 AuthDialogCallback.java
-rw-r--r--  1 lenovo lenov  3964 Apr 18 18:18 AuthDialog.java
-rw-r--r--  1 lenovo lenov  6547 Apr 18 18:18 AuthPanelController.java
-rw-r--r--  1 lenovo lenov   115 Apr 18 18:18 OWNERS
-rw-r--r--  1 lenovo lenov  4316 Apr 18 18:18 Utils.java

有代码可见,框架在SystemUI部分也给出了一些调整,不再叫BiometricDialogView, 而改成了AuthBiometricView。

 

SystemUI端实现AuthBiometricView相关类图

Android R authContainerView

由上可知,其实现不仅支持生物特征验证还支持强密码(例如:Pattern)验证。

 

前面提到Android Q中遇到Menu键不消失问题,现直接SystemUI内部AuthController注册监听Intent.ACTION_CLOSE_SYSTEM_DIALOGS广播的方式dismiss。
不再需要BiometricService发送消息来HideDialog。

    @VisibleForTesting
    AuthController(Context context, CommandQueue commandQueue, Injector injector) {
        super(context);
        mCommandQueue = commandQueue;
        mInjector = injector;

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

        context.registerReceiver(mBroadcastReceiver, filter);
    }

    @VisibleForTesting
    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (mCurrentDialog != null
                    && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
                mCurrentDialog.dismissWithoutCallback(true /* animate */);
                mCurrentDialog = null;

                try {
                    if (mReceiver != null) {
                        mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
                                null /* credentialAttestation */);
                        mReceiver = null;
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "Remote exception", e);
                }
            }
        }
    };

由SystemUI发送dismiss消息到BiometricService去cancelAuthentication()取消指纹监听,同时往上发送onAuthenticationError(error, errorMessage)消息到3rd app。释放当前Session: mCurrentAuthSession。
FingerprintService取消指纹监听后,会往BiometricService上报Error。

    private void handleOnDismissed(int reason, @Nullable byte[] credentialAttestation) {
        if (mCurrentAuthSession == null) {
            Slog.e(TAG, "onDismissed: " + reason + ", auth session null");
            return;
        }

        logDialogDismissed(reason);

        try {
            switch (reason) {
                case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
                    mKeyStore.addAuthToken(credentialAttestation);
                case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED:
                case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED:
                    if (mCurrentAuthSession.mTokenEscrow != null) {
                        mKeyStore.addAuthToken(mCurrentAuthSession.mTokenEscrow);
                    }
                    mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded(
                            Utils.getAuthenticationTypeForResult(reason));
                    break;

                case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
                    mCurrentAuthSession.mClientReceiver.onDialogDismissed(reason);
                    // Cancel authentication. Skip the token/package check since we are cancelling
                    // from system server. The interface is permission protected so this is fine.
                    cancelInternal(null /* token */, null /* package */,
                            mCurrentAuthSession.mCallingUid, mCurrentAuthSession.mCallingPid,
                            mCurrentAuthSession.mCallingUserId, false /* fromClient */);
                    break;

                case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
                    mCurrentAuthSession.mClientReceiver.onError(
                            mCurrentAuthSession.mModality,
                            BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
                            0 /* vendorCode */
                    );
                    // Cancel authentication. Skip the token/package check since we are cancelling
                    // from system server. The interface is permission protected so this is fine.
                    cancelInternal(null /* token */, null /* package */, Binder.getCallingUid(),
                            Binder.getCallingPid(), UserHandle.getCallingUserId(),
                            false /* fromClient */);
                    break;

                case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED:
                case BiometricPrompt.DISMISSED_REASON_ERROR:
                    mCurrentAuthSession.mClientReceiver.onError(
                            mCurrentAuthSession.mModality,
                            mCurrentAuthSession.mErrorEscrow,
                            mCurrentAuthSession.mVendorCodeEscrow
                    );
                    break;

                default:
                    Slog.w(TAG, "Unhandled reason: " + reason);
                    break;
            }

            // Dialog is gone, auth session is done.
            mCurrentAuthSession = null;

        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception", e);
        }
    }

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值