Android10.0 锁屏分析-KeyguardPatternView图案锁分析

首先一起看看下面这张图:

通过前面锁屏加载流程可以知道在KeyguardSecurityContainer中使用getSecurityView()根据不同的securityMode inflate出来,并添加到界面上的。
我们知道,Pattern锁所使用的layout是 R.layout.keyguard_pattern_view;

<com.android.keyguard.KeyguardPatternView ...>
...<com.android.internal.widget.LockPatternViewandroid:id="@+id/lockPatternView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:layout_marginEnd="8dip"android:layout_marginBottom="4dip"android:layout_marginStart="8dip"android:layout_gravity="center_horizontal"android:gravity="center"android:clipChildren="false"android:clipToPadding="false" />
...</FrameLayout>
</com.android.keyguard.KeyguardPatternView>

那么图案解锁的滑动事件处理,就是在LockPatternView,是一个系统公共控件,下面我们就分析一下这个view是如何处理触摸输入的:
frameworks/base/core/java/com/android/internal/widget/LockPatternView.java

    @Overridepublic boolean onTouchEvent(MotionEvent event) {if (!mInputEnabled || !isEnabled()) {return false;}switch(event.getAction()) {case MotionEvent.ACTION_DOWN:handleActionDown(event);return true;case MotionEvent.ACTION_UP:handleActionUp();return true;case MotionEvent.ACTION_MOVE:handleActionMove(event);return true;case MotionEvent.ACTION_CANCEL:if (mPatternInProgress) {setPatternInProgress(false);resetPattern();notifyPatternCleared();}if (PROFILE_DRAWING) {if (mDrawingProfilingStarted) {Debug.stopMethodTracing();mDrawingProfilingStarted = false;}}return true;}return false;}

几种事件类型:

事件简介
ACTION_DOWN手指初次触摸到屏幕时触发
ACTION_MOVE手指在屏幕上滑动时触发,会多次触发
ACTION_UP手指离开屏幕时触发
ACTION_CANCEL事件被上层拦截时触发
ACTION_OUTSIDE手指不在控件区域时触发

不同的MotionEvent对应几个不同的handle方法处理,代码行数太多,我们这里大致总结如下:

  • ACTION_DOWN(handleActionDown):根据触摸事件的坐标,使用算法detectAndAddHit(x, y)获取是否有命中的点,如果有,会调用addCellToPattern将命中的Cell添加到mPattern中,后即回调mOnPatternListener.onPatternStart()通知监听器,KeyguardPatternView实现并监听了OnPatternListener,做了清除安全提示内容的动作。另外计算需要重绘区域,并调用invalidate进行局部重绘。
  • ACTION_MOVE(handleActionMove):在这里 LockPatternView会对所有的历史坐标加当前事件坐标遍历for (int i = 0; i < historySize + 1; i++),获取命中点,另外如果ACTION_DOWN时没有获取到命中点,流程同上面的ACTION_UP,然后也会回调mOnPatternListener.onPatternStart()。最后会把所有motionevent对应的重绘区域进行union,并调用invalidate进行局部重绘。

关于历史坐标
  为了效率,Android系统在处理ACTION_MOVE事件时会将连续的几个多触点移动事件打包到一个MotionEvent对象中。我们可以通过getX(int)和getY(int)来获得最近发生的一个触摸点事件的坐标,然后使用getHistorical(int,int)和getHistorical(int,int)来获得时间稍早的触点事件的坐标,二者是发生时间先后的关系。所以,我们应该先处理通过getHistoricalXX相关函数获得的事件信息,然后在处理当前的事件信息。

for (int i = 0; i < historySize + 1; i++) {final float x = i < historySize ? event.getHistoricalX(i) : event.getX();final float y = i < historySize ? event.getHistoricalY(i) : event.getY();...
}
  • ACTION_UP(handleActionUp):如果mPattern不为空的话,会重置mPatternInProgress,取消动画,然后回调mOnPatternListener.onPatternDetected(final List<LockPatternView.Cell> pattern),这时候就开始图案解锁的验证了。
  • ACTION_CANCEL:重置pattern状态,回调mOnPatternListener.onPatternCleared()
图案解锁验证

src/com/android/keyguard/KeyguardPatternView.java

    private class UnlockPatternListener implements LockPatternView.OnPatternListener {...@Overridepublic void onPatternDetected(final List<LockPatternView.Cell> pattern) {if (DEBUG) Log.d(TAG, "onPatternDetected");mKeyguardUpdateMonitor.setCredentialAttempted();mLockPatternView.disableInput();if (mPendingLockCheck != null) {mPendingLockCheck.cancel(false);}final int userId = KeyguardUpdateMonitor.getCurrentUser();if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {mLockPatternView.enableInput();onPatternChecked(userId, false, 0, false /* not valid - too short */);return;}if (LatencyTracker.isEnabled(mContext)) {LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);}mPendingLockCheck = LockPatternChecker.checkCredential(mLockPatternUtils,LockscreenCredential.createPattern(pattern),    // 这里跟进去,会发现将 pattern转化成了 byte[]userId,new LockPatternChecker.OnCheckCallback() {@Overridepublic void onEarlyMatched() {if (DEBUG) Log.d(TAG, "onEarlyMatched");if (LatencyTracker.isEnabled(mContext)) {LatencyTracker.getInstance(mContext).onActionEnd(ACTION_CHECK_CREDENTIAL);}onPatternChecked(userId, true /* matched */, 0 /* timeoutMs */,true /* isValidPattern */);}@Overridepublic void onChecked(boolean matched, int timeoutMs) {if (DEBUG) Log.d(TAG, "onChecked matched:" + matched);if (LatencyTracker.isEnabled(mContext)) {LatencyTracker.getInstance(mContext).onActionEnd(ACTION_CHECK_CREDENTIAL_UNLOCKED);}mLockPatternView.enableInput();mPendingLockCheck = null;if (!matched) {onPatternChecked(userId, false /* matched */, timeoutMs,true /* isValidPattern */);}}@Overridepublic void onCancelled() {if (DEBUG) Log.d(TAG, "onCancelled");// We already got dismissed with the early matched callback, so we// cancelled the check. However, we still need to note down the latency.if (LatencyTracker.isEnabled(mContext)) {LatencyTracker.getInstance(mContext).onActionEnd(ACTION_CHECK_CREDENTIAL_UNLOCKED);}}});if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {mCallback.userActivity();mCallback.onUserInput();}}...}

在绘制密码后手指抬起的时候,如果已存的有效点数达到4个及以上,就会使用LockPatternChecker.checkCredential 方法调用 task.execute() 启动一个AsyncTask, 并在doInBackground中调用LockPatternUtils.checkCredential 进行密码验证,此时pattern会被转化成字节形式(LockscreenCredential.createPattern(pattern) 这里跟进去,会发现将 pattern转化成了 byte[])

// LockPatternUtils.java
public static byte[] patternToByteArray(List<LockPatternView.Cell> pattern) {if (pattern == null) {return new byte[0];}final int patternSize = pattern.size();byte[] res = new byte[patternSize];for (int i = 0; i < patternSize; i++) {LockPatternView.Cell cell = pattern.get(i);res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');}return res;
}

最终和密码锁PIN码锁一样,都是远程调用到LockSettingsService 的 checkCredential 接口进行验证。
Keyguard接收用户输入的密码会通过Binder到framework层的LockSettingsService,LockSettingsService经过一系列调用会通过getGateKeeperService获取GateKeeperService然后调用verifyChallenge方法将密码继续忘底层传递,framework的调用栈如下:

java.lang.Throwab
comandroid.locksettings.1locksettings.LockSettingsService. spBasedDoVerifyCredential(LockSettingsService. java:2724)COT3767075server.ocksettingsLockSettingsService.doVerifyCredentia1(LockSettingsSeryice.java:2020comandroservercom android.server.locksettings.LockSettingsService.doVerifyCredential(LockSettingsService. jaya:1999atcom android.server.locksettings.LockSettingsService. checkCredential(LockSettingsService. java:1972)com android.internal.widget.ILockSettings$Stub.onTransact(ILockSettings.java:542atatexecTransactInternal(Binder.java:1159)execTransact(Binder.java:1123)atSyntheticPasswordllanager. unwrapPasswordBasedSyntheticPassword(SyntheticPasswordllanager. java: 1016
android.os.Binderandroid.os.Binder

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/379194.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS NEXT学习——@BuilderParam装饰器

初步理解&#xff0c;相当于VUE的插槽slot Builder function overBuilder() {}Component struct Child {label: string ChildBuilder customBuilder() {}Builder customChangeThisBuilder() {}BuilderParam customBuilderParam: () > void this.customBuilder; // 使用自定…

RK3568笔记三十六:LED驱动开发(设备树)

若该文为原创文章&#xff0c;转载请注明原文出处。 记录使用设备树编写一个简单的 LED 灯驱动程序 一、编程思路 程序编写的主要内容为添加 LED 灯的设备树节点、在驱动程序中使用 of 函数获取设备节点中的 属性&#xff0c;编写测试应用程序。 • 首先向设备树添加 LED 设备…

使用Python Turtle绘制圣诞树和装饰

简介(❤ ω ❤) 在这篇文章中&#xff0c;我们将探索如何使用Python的Turtle模块来绘制一个充满节日气氛的圣诞树&#xff0c;以及一些可爱的装饰品。Turtle是一个受Logo语言启发的图形库&#xff0c;非常适合初学者学习编程和创建图形。 码农不是吗喽&#xff08;大学生版&…

STM32智能工业自动化监控系统教程

目录 引言环境准备智能工业自动化监控系统基础代码实现&#xff1a;实现智能工业自动化监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;工业自动化与管理问题解决方案与优化收尾与总结 1. 引言 智能…

初学者如何通过建立个人博客盈利

建立个人博客不仅能让你在网上表达自己&#xff0c;还能与他人建立联系。通过博客&#xff0c;可以创建自己的空间&#xff0c;分享想法和故事&#xff0c;并与有相似兴趣和经历的人交流。 本文将向你展示如何通过建立个人博客来实现盈利。你将学习如何选择博客主题、挑选合适…

React学习笔记02-----React基本使用

一、React简介 想实现页面的局部刷新&#xff0c;而不是整个网页的刷新。AJAXDOM可以实现局部刷新 1.特点 &#xff08;1&#xff09;虚拟DOM 开发者通过React来操作原生DOM&#xff0c;从而构建页面。 React通过虚拟DOM来实现&#xff0c;可以解决DOM的兼容性问题&#x…

如何在gitee上创建远程仓库?

登录gitee网站后 填写自己的仓库信息后点击创建 然后来到一个新的界面可以看到自己的仓库地址 这样一个空白的仓库就建立好了 也可以按需选择初始化仓库

Python爬虫入门篇学习记录

免责声明 本文的爬虫知识仅用于合法和合理的数据收集&#xff0c;使用者需遵守相关法律法规及目标网站的爬取规则&#xff0c;尊重数据隐私&#xff0c;合理设置访问频率&#xff0c;不得用于非法目的或侵犯他人权益。因使用网络爬虫产生的任何法律纠纷或损失&#xff0c;由使用…

快手开源LivePortrait,实现表情姿态极速迁移,GitHub 6.5K Star

近日&#xff0c;快手可灵大模型团队开源了名为LivePortrait的可控人像视频生成框架&#xff0c;能够准确、实时地将驱动视频的表情、姿态迁移到静态或动态人像视频上&#xff0c;生成极具表现力的视频结果。如下动图所示&#xff1a; 来自网友测试LivePortrait 来自网友测试Li…

JavaWeb入门程序解析(Spring官方骨架、配置起步依赖、SpringBoot父工程、内嵌Tomcat)

3.3 入门程序解析 关于web开发的基础知识&#xff0c;我们可以告一段落了。下面呢&#xff0c;我们在基于今天的核心技术点SpringBoot快速入门案例进行分析。 3.3.1 Spring官方骨架 之前我们创建的SpringBoot入门案例&#xff0c;是基于Spring官方提供的骨架实现的。 Sprin…

LeetCode-随机链表的复制

. - 力扣&#xff08;LeetCode&#xff09; 本题思路&#xff1a; 首先注意到随机链表含有random的指针&#xff0c;这个random指针指向是随机的&#xff1b;先一个一个节点的拷贝&#xff0c;并且把拷贝的节点放在拷贝对象的后面&#xff0c;再让拷贝节点的next指向原链表拷贝…

Burp安全扫描Web应用

一、浏览器设置代理 如下图所示&#xff0c;点击火狐浏览器的“扩展和主题”&#xff0c;搜索“代理”。 如下图所示&#xff0c;选择搜索到的第一个代理&#xff08;选择任何一个都可以&#xff09;。 如上图所示&#xff0c;第一个点击后&#xff0c;进入如下页面&#xff0…

CT金属伪影去除的去噪扩散概率模型| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 A denoising diffusion probabilistic model for metal artifact reduction in CT CT金属伪影去除的去噪扩散概率模型 01 文献速递介绍 CT图像中的金属伪影是在CT扫描视野内存在金属物体&#xff08;如牙科填充物、骨科假体、支架、手术器械等&#xff09;时出…

爬虫(一)——爬取快手无水印视频

前言 最近对爬虫比较感兴趣&#xff0c;于是浅浅学习了一些关于爬虫的知识。爬虫可以实现很多功能&#xff0c;非常有意思&#xff0c;在这里也分享给大家。由于爬虫能实现的功能太多&#xff0c;而且具体的实现方式也有所不同&#xff0c;所以这里开辟了一个新的系列——爬虫…

破解反爬虫策略 /_guard/auto.js(二)实战

这次我们用上篇文章讲到的方法来真正破解一下反爬虫策略&#xff0c;这两个案例是两个不同的网站&#xff0c;一个用的是 /_guard/auto.js&#xff0c;另一个用的是/_guard/delay_jump.js。经过解析发现这两个网站用的反爬虫策略基本是一模一样&#xff0c;只不过在js混淆和生成…

桥接器设计模式例题

笔有大、中、小三种型号&#xff0c;纸有A4、8K、16K三种型号&#xff0c;颜料有红、蓝、绿三种&#xff0c;请采用桥接器设计模型进行系统设计&#xff0c;能够使用不同型号的笔在不同型号的纸上利用不同颜色的颜料进行绘画。 下面这段代码展示了一个简单的桥接模式(桥接模式)…

Vue--Router(路由)

目录 一 Router(路由) 1.作用 2.实现步骤 3.注意 一 Router(路由) 1.作用 Router又叫做路由&#xff0c;简单来说&#xff0c;就是用来实现vue的页面之间跳转的。 我们都知道&#xff0c;使用vue必然会涉及到很多个组件&#xff0c;也就是页面&#xff0c;而页面之间肯定需…

小程序-模板与配置

一、WXML模板语法 1.数据绑定 2.事件绑定 什么是事件 小程序中常用的事件 事件对象的属性列表 target和currentTarget的区别 bindtap的语法格式 在事件处理函数中为data中的数据赋值 3.事件传参与数据同步 事件传参 &#xff08;以下为错误示例&#xff09; 以上两者的…

【通信协议-RTCM】MSM语句(1) - 多信号GNSS观测数据消息格式

注释&#xff1a; RTCM响应消息1020为GLONASS星历信息&#xff0c;暂不介绍&#xff0c;前公司暂未研发RTCM消息类型版本的DR/RTK模块&#xff0c;DR/RTK模块仅NMEA消息类型使用 注释&#xff1a; 公司使用的多信号语句类型为MSM4&MSM7&#xff0c;也应该是运用最广泛的语句…

算法笔记——LCR

一.LCR 152. 验证二叉搜索树的后序遍历序列 题目描述&#xff1a; 给你一个二叉搜索树的后续遍历序列&#xff0c;让你判断该序列是否合法。 解题思路&#xff1a; 根据二叉搜索树的特性&#xff0c;二叉树搜索的每一个结点&#xff0c;大于左子树&#xff0c;小于右子树。…