手指在指纹传感器上摸一下就能解锁,Keyguard是怎么做到的呢?

下面我们就跟着源码,解析这整个过程。

何时开始监听指纹传感器?

先来看下IKeyguardService这个binder接口有哪些回调吧

// 当另一个窗口使用FLAG_SHOW_ON_LOCK_SCREEN解除Keyguard时PhoneWindowManager调用

public void setOccluded(boolean isOccluded, boolean animate) throws android.os.RemoteException;

// 添加锁屏状态回调

public void addStateMonitorCallback(com.android.internal.policy.IKeyguardStateCallback callback) throws android.os.RemoteException;

// 核验解锁(用于快捷启动)

public void verifyUnlock(com.android.internal.policy.IKeyguardExitCallback callback) throws android.os.RemoteException;

// 解除锁屏

public void dismiss(com.android.internal.policy.IKeyguardDismissCallback callback) throws android.os.RemoteException;

// 屏保开始(Intent.ACTION_DREAMING_STARTED)

public void onDreamingStarted() throws android.os.RemoteException;

// 屏保结束(Intent.ACTION_DREAMING_STOPPED)

public void onDreamingStopped() throws android.os.RemoteException;

// 设备开始休眠 reason:OFF_BECAUSE_OF_USER/OFF_BECAUSE_OF_ADMIN/OFF_BECAUSE_OF_TIMEOUT

public void onStartedGoingToSleep(int reason) throws android.os.RemoteException;

// 休眠完成

public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) throws android.os.RemoteException;

// 设备开始唤醒

public void onStartedWakingUp() throws android.os.RemoteException;

// 唤醒完成

public void onFinishedWakingUp() throws android.os.RemoteException;

// 正在亮屏

public void onScreenTurningOn(com.android.internal.policy.IKeyguardDrawnCallback callback) throws android.os.RemoteException;

// 已经亮屏完成

public void onScreenTurnedOn() throws android.os.RemoteException;

// 正在灭屏

public void onScreenTurningOff() throws android.os.RemoteException;

// 灭屏完成

public void onScreenTurnedOff() throws android.os.RemoteException;

// 外部应用取消Keyguard接口

public void setKeyguardEnabled(boolean enabled) throws android.os.RemoteException;

// 开机系统准备完成回调

public void onSystemReady() throws android.os.RemoteException;

// 延时锁屏 (用于自动休眠)

public void doKeyguardTimeout(android.os.Bundle options) throws android.os.RemoteException;

// 切换用户中

public void setSwitchingUser(boolean switching) throws android.os.RemoteException;

// 设置当前用户

public void setCurrentUser(int userId) throws android.os.RemoteException;

// 系统启动完成回调

public void onBootCompleted() throws android.os.RemoteException;

// Keyguard后面的activity已经绘制完成,可以开始移除壁纸和Keyguard flag

public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) throws android.os.RemoteException;

// 通知Keyguard对power键做特殊处理,使设备不进行休眠或唤醒而是启动Home(目前是空实现)

public void onShortPowerPressedGoHome() throws android.os.RemoteException;

在这么多接口里,有

onStartedGoingToSleep/

onFinishedGoingToSleep/

onScreenTurningOff/

onScreenTurnedOff

这四个接口是在power键按下后触发,其中onStartedGoingToSleep最先被触发,他们的

调用顺序我会在后文里讲解。

而我们的指纹传感器监听,就是在onStartedGoingToSleep时开始的。

代码逻辑由在KeyguardService中由中间类KeyguardMediator调用到KeyguardUpdateMonitor

android/frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java

protected void handleStartedGoingToSleep(int arg1) {

...

updateFingerprintListeningState();

}

private void updateFingerprintListeningState() {

// If this message exists, we should not authenticate again until this message is

// consumed by the handler

if (mHandler.hasMessages(MSG_FINGERPRINT_AUTHENTICATION_CONTINUE)) {

return;

}

mHandler.removeCallbacks(mRetryFingerprintAuthentication);

boolean shouldListenForFingerprint = shouldListenForFingerprint();

if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {

stopListeningForFingerprint();

} else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING

&& shouldListenForFingerprint) {

startListeningForFingerprint();

}

}

在同时判断mFingerprintRunningState和shouldListenForFingerprint后,

Keyguard在startListeningForFingerprint中真正使用FingerprintManager监听指纹传感器

指纹传感器的监听方法

private void startListeningForFingerprint() {

if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {

setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);

return;

}

if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");

int userId = ActivityManager.getCurrentUser();

if (isUnlockWithFingerprintPossible(userId)) {

if (mFingerprintCancelSignal != null) {

mFingerprintCancelSignal.cancel();

}

mFingerprintCancelSignal = new CancellationSignal();

mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);

setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);

}

}

真正到了使用指纹识别功能的时候,你会发现其实很简单,只是调用 FingerprintManager 类的的方法authenticate()而已,然后系统会有相应的回调反馈给我们,该方法如下:

public void authenticate(CryptoObject crypto, CancellationSignal cancel, int flags, AuthenticationCallback callback, Handler handler, int userId)

该方法的几个参数解释如下:

第一个参数是一个加密对象。目前为null

第二个参数是一个 CancellationSignal 对象,该对象提供了取消操作的能力。创建该对象也很简单,使用 new CancellationSignal() 就可以了。

第三个参数是一个标志,默认为0。

第四个参数是 AuthenticationCallback 对象,它本身是 FingerprintManager 类里面的一个抽象类。该类提供了指纹识别的几个回调方法,包括指纹识别成功、失败等。需要我们重写。

最后一个 Handler,可以用于处理回调事件,可以传null。

用户id

下面只需要在mAuthenticationCallback继承AuthenticationCallback这个抽象方法,重写回调接口

private FingerprintManager.AuthenticationCallback mAuthenticationCallback

= new AuthenticationCallback() {

@Override

public void onAuthenticationFailed() {

handleFingerprintAuthFailed();

};

@Override

public void onAuthenticationSucceeded(AuthenticationResult result) {

Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");

handleFingerprintAuthenticated(result.getUserId());

Trace.endSection();

}

@Override

// 指纹验证

public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {

handleFingerprintHelp(helpMsgId, helpString.toString());

}

@Override

// 指纹验证时回调

public void onAuthenticationError(int errMsgId, CharSequence errString) {

}

@Override

// 获取到指纹时回调

public void onAuthenticationAcquired(int acquireInfo) {

handleFingerprintAcquired(acquireInfo);

}

};

获取指纹后,Keyguard做了哪些事?

从AuthenticationCallback里可以看出,获取指纹回调首先发生在 onAuthenticationAcquired 中, 我们先看代码

private void handleFingerprintAcquired(int acquireInfo) {

if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {

return;

}

for (int i = 0; i < mCallbacks.size(); i++) {

KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();

if (cb != null) {

cb.onFingerprintAcquired();

}

}

}

首先用acquireInfo参数判断是否正确获取指纹,之后遍历KeyguardUpdateMonitorCallback,进行回调。

重写onFingerprintAcquired方法的只有FingerprintUnlockController,FingerprintUnlockController就是

用于协调UI的所有指纹解锁操作的控制器。

@Override

public void onFingerprintAcquired() {

...

mWakeLock = mPowerManager.newWakeLock(

PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);

mWakeLock.acquire();

mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,

FINGERPRINT_WAKELOCK_TIMEOUT_MS);

}

...

}

onFingerprintAcquired的核心逻辑全部是和WakeLock相关的,

获取WakeLock,并发送一条延时消息,15秒后,释放WakeLock。

下一步就发生在,onFingerprintAuthenticated回调中了,实现onFingerprintAuthenticated接口的不止一处,但真正实现解锁的还是在FingerprintUnlockController中

@Override

public void onFingerprintAuthenticated(int userId) {

...

startWakeAndUnlock(calculateMode());

}

private int calculateMode() {

boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();

boolean deviceDreaming = mUpdateMonitor.isDreaming();

if (!mUpdateMonitor.isDeviceInteractive()) {

if (!mStatusBarKeyguardViewManager.isShowing()) {

return MODE_ONLY_WAKE;

} else if (mDozeScrimController.isPulsing() && unlockingAllowed) {

return MODE_WAKE_AND_UNLOCK_PULSING;

} else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {

return MODE_WAKE_AND_UNLOCK;

} else {

return MODE_SHOW_BOUNCER;

}

}

if (unlockingAllowed && deviceDreaming) {

return MODE_WAKE_AND_UNLOCK_FROM_DREAM;

}

if (mStatusBarKeyguardViewManager.isShowing()) {

if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {

return MODE_DISMISS_BOUNCER;

} else if (unlockingAllowed) {

return MODE_UNLOCK;

} else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {

return MODE_SHOW_BOUNCER;

}

}

return MODE_NONE;

}

这段代码逻辑很清晰,就是根据锁屏的状态计算指纹解锁的模式

public void startWakeAndUnlock(int mode) {

...

boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();

mMode = mode;

if (!wasDeviceInteractive) {

mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT");

}

releaseFingerprintWakeLock();

switch (mMode) {

...

}

}

startWakeAndUnlock中的代码经过简化后,只剩三部分:

1.先判断设备唤醒状态,是用PowerManager的wakeUp接口点亮屏幕

2.然后释放在acquire阶段获取的WakeLock

3.最后在根据上面calculateMode得出的解锁模式,进行真正的解锁动作,这在之前的解锁流程中已经分析过,这里不再做分析。

这里面值得我们注意的是wakeUp接口, 下面我们稍微对该接口进行一点探究

PowerManager的wakeUp接口

我们知道上层应用要唤醒系统一般只能依靠两种方式:

1.在应用启动Activity时候设置相应的window的flags,通过WMS来唤醒系统;

即通过WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON

2.在应用申请wakelock锁时附带ACQUIRE_CAUSES_WAKEUP标志

PowerManager的wakeup接口属性是@hide的,对一般应用是不可见的,而我们的SystemUI就不存在调用问题。

SystemUI通过调用第三种方式:PowerManager的wakeup接口,来强制唤醒系统,如果该设备处于睡眠状态,调用该接口会立即唤醒系统,比如按Power键,来电,闹钟等场景都会调用该接口。唤醒系统需要android.Manifest.permission#DEVICE_POWER的权限,我们可以看到SystemUI的Manifest文件里已经添加了该权限。

PowerManagerService唤醒的流程请看流程图:

PMS的wakeUp流程

从流程可以看到,亮屏流程可以和KeyguardService中的回调对应上了。

总结

其实指纹解锁的本质是在KeyguardService收到从PMS到WMS的调用中,在StartedGoingToSleep时就开始使用FingerprintManager的authticate开始监听感器,在FIngerManager验证成功时,使用PowerManagerService点亮屏幕,进行解锁流程。

android keyguard,Android8.1 SystemUI Keyguard之指纹解锁流程相关推荐

  1. android流程点击开机键熄屏,一种基于android系统的灭屏状态下指纹解锁加速亮屏方法与流程...

    本发明涉及android系统解锁显示方法,尤其涉及一种基于android系统的灭屏状态下指纹解锁加速亮屏方法. 背景技术: 目前,随着指纹技术越来越普及,很多android系统设备都带有指纹外设,特别 ...

  2. android 解锁流程,Android Q 指纹解锁流程

    Android Q 指纹解锁流程 // Authentation Finger Schedule: (close Screen, Authentation with finger(Success)) ...

  3. android指纹解锁动画,Android8.1 SystemUI Keyguard之指纹解锁流程

    手指在指纹传感器上摸一下就能解锁,Keyguard是怎么做到的呢? 下面我们就跟着源码,解析这整个过程. 何时开始监听指纹传感器? 先来看下IKeyguardService这个binder接口有哪些回 ...

  4. Android8.1 SystemUI 之图案锁验证流程

    2019独角兽企业重金招聘Python工程师标准>>> 在Keyguard之滑动解锁流程一文中,我们已经分析过,不同的安全锁类型是在KeyguardSecurityContainer ...

  5. Android 4.0 ICS SystemUI浅析——StatusBar加载流程分析

    前面两篇文章< Android 4.0 ICS SystemUI浅析--SystemUI启动流程>.< Android 4.0 ICS SystemUI浅析--StatusBar结构 ...

  6. 指纹录入和指纹解锁流程

    粗略了解下指纹的录入和解锁流程, 记录如下 Android P Finger Enroll:     1.Settings         FingerprintEnrollIntroduction ...

  7. 支付宝指纹解锁流程分析以及代码实现

    经常使用支付宝的的指纹登录,既安全,又方便.抽空就结合着指纹的相关知识,理了一下这个流程. 在梳理支付宝指纹流程之前,先熟悉一下关于指纹解锁的知识. 指纹解锁的相关类位于 LocalAuthentic ...

  8. android开发指纹解锁,Android-指纹解锁技术

    什么是指纹解锁技术 指纹解锁技术原理理解 指纹解锁技术的优势和缺点 在Android中的应用开发 什么是指纹解锁技术 根据人的指纹来验证是否能够解锁的技术,类似于通过输入密码来解锁,都是通过一定的数字 ...

  9. 息屏指纹解锁性能优化 TP LCD

    需求背景 .客户反馈我司的指纹解锁机器冷屏(息屏)解锁下速度太慢,体验很差,而对比机却非常快 .对比发现,我司机器跟市面品牌机的冷屏解锁速度差了不是一个等级, 急待改善. 既然要优化功能,首先要做到理 ...

最新文章

  1. 【2007-5】【素数算式】
  2. Linux内核访问外设I O资源的方式
  3. 三层架构介绍和MVC设计模型介绍
  4. Tensorflow 官方版教程中文版
  5. 排序(Sort)--【一】
  6. python 制作简单网站_新手小白 做python爬虫 爬什么网站比较简单?
  7. semi-global matching 算法总结
  8. linux 集成调试工具,linux下can调试工具canutils安装过程记录
  9. odoo开发笔记 -- 附件上传
  10. 电脑常见故障排查思路
  11. deepin linux 安装jdk,deepin安装JDK
  12. UDP进程terminated
  13. 计算机专业国际竞赛,国际计算机竞赛深度剖析
  14. 解决linux“嘟嘟”的报警声
  15. Pytorch踩坑记之交叉熵(nn.CrossEntropy,nn.NLLLoss,nn.BCELoss的区别和使用)
  16. 《MetaSploit渗透测试魔鬼训练营》之WEB应用渗透技术
  17. CISCO asa5520 端口映射
  18. Python学习笔记——常用基本语法
  19. Window7定期批处理删除指定文件且不弹出黑窗口的方法
  20. 星域cdn概念股票_星域CDN拿下全国性经营牌照 行业进入新巨头时代

热门文章

  1. uds下载服务流程图_UDS诊断全集,干货分享
  2. Android view变形,Android SurfaceView预览变形完美解决方法
  3. php 中文截断,PHP中实现中文字串截取无乱码的解决方法
  4. jar注册成服务器,Spring Boot项目生成jar包,并在windows服务器中注册成服务,开机启动(示例代码)...
  5. linux 脚本 变量为空,Shell判断一个变量是否为空
  6. python invalid literal for int_求助!运行出现错误“ValueError: invalid literal for int() ··...
  7. php网页审批权限设置,Linux下ThinkPHP网站目录权限设置
  8. python sendfile_python发邮件
  9. html 字显示效果,js原生文字一个一个显示效果
  10. 手动启动_电站首台机组首次手动开机启动一次性成功