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
相关文章:
Android10.0 锁屏分析-KeyguardPatternView图案锁分析
首先一起看看下面这张图: 通过前面锁屏加载流程可以知道在KeyguardSecurityContainer中使用getSecurityView()根据不同的securityMode inflate出来,并添加到界面上的。 我们知道,Pattern锁所使用的layout是 R.layout.keyguard_pattern_view&a…...
Python 装饰器:函数的函数,代码的艺术
引言 在Python中,装饰器是一种强大的功能,允许程序员在不修改原函数源码的情况下增强或修改函数行为。装饰器本质上是一个接收函数作为参数的高阶函数,并返回一个新的函数或修改原函数的行为。这种机制极大地提高了代码的复用性、可读性和模…...
安全防御2
实验要求: 实验过程: 7,办公区设备可以通过电信链路和移动链路上网(多对多的NAT,并且需要保留一个公网IP不能用来转换): 新建电信区: 新建移动区: 将对应接口划归到各自区域: 新建…...
C语言 ——— 打印水仙花数
目录 何为水仙花数 题目要求 代码实现 何为水仙花数 “水仙花数”是指一个n位数,其各位数字的n次方之和等于该数本身 如:153 1^3 5^3 3^3,则153就是一个“水仙花数” 题目要求 求出0~100000的所有“水仙花数”并输出 代码实现 #i…...
「Conda」在Linux系统中安装Conda环境管理器
在Linux系统中安装Conda环境管理器是一个相对简单的过程。 1. 准备工作 确保你的Linux系统已经更新到最新版本,并安装了基本的开发工具和库。打开终端,执行以下命令: sudo apt-get update sudo apt-get upgrade sudo apt-get install build-essential2. 安装Miniconda或An…...
9.11和9.9哪个大?GPT-4o也翻车了
今天刷到了这个问题,心血来潮去问下chatgpt-4o,没想到疯狂翻车... 第一次问: GPT一开始给出了难绷的解答,让我想起了某短视频软件评论区里对某歌手节目排名的质疑哈哈哈哈哈 但是在接下来的进一步询问和回答中它反应过来了。 第…...
[开源]语雀+Vercel:打造免费个人博客网站
大家好,我是白露。 今天我想和大家分享我的今年的第一个开源项目 —— 基于语雀+Nextjs+Vercel实现免费的博客系统。 简单来说,你在语雀写博客,然后直接一键同步到个人网站上,网站自动部署! 而且,整个过程几乎不需要额外的成本,也不用充值语雀超级会员,hh。这个项目…...
使用ElementUI和element-china-area-data库实现省市区三级联动组件封装
在前端开发中,省市区三级联动是一个常见的需求。今天我们将使用Vue.js和ElementUI组件库,结合element-china-area-data库,来实现一个省市区三级联动的组件。这个组件不仅可以提高用户体验,还能大大简化我们的代码。接下来…...
0718,TCP协议,三次握手,四次挥手
目录 上课喵: TCP(Transmission Control Protocol,传输控制协议)的状态迁移图 TCP连接的状态迁移图 状态迁移说明: 注意: big_htonl.c 字节序转换 addr.c IP地址的转换 作业喵: …...
如何安装Visual Studio Code
Visual Studio Code(简称 VS Code) Visual Studio Code 是一款由微软开发的免费、开源的现代化轻量级代码编辑器。 主要特点包括: 跨平台:支持 Windows、Mac 和 Linux 等主流操作系统,方便开发者在不同平台上保持一…...
vi 编辑器快捷生成 main 函数和基本框架
step1: 执行 sudo vi /etc/vim/vimrc (修改vimrc需要管理员权限:sudo) step2:输入用户密码,回车, 编辑vimrc文件 step3:在尾行输入以下代码(可复制) map mf i#include<stdio.h><ESC>o#includ…...
npm相关指令
切换镜像 腾讯镜像 npm config set registry https://mirrors.cloud.tencent.com/npm/ 淘宝镜像(新版) npm config set registry https://registry.npmmirror.com 淘宝镜像(旧版,已弃用) npm config set regist…...
为什么不要碰自媒体
要是失业了,搞自媒体,可行吗?毫无希望! 如今的自媒体早卷得不成样子了,很难再有机会,根本原因在于几乎没有增量用户的同时,存量用户也不再有剩余时间,全量用户的时间早已被几个自媒…...
酷炫末世意境背景404单页HTML源码
源码介绍 酷炫末世意境背景404单页HTML源码,背景充满着破坏一切的意境,彷佛末世的到来,可以做网站错误页或者丢失页面,将下面的代码放到空白的HTML里面,然后上传到服务器里面,设置好重定向即可 效果预览 …...
PHP 调用 1688 详情 API 接口的实战攻略
在电商领域,获取准确和详细的商品信息对于业务的发展至关重要。1688 作为国内知名的批发采购平台,其详情 API 接口为开发者提供了丰富的数据资源。本文将为您详细介绍如何使用 PHP 调用 1688 详情 API 接口。 一、前期准备 注册 1688 开放平台账号&#…...
SAP ABAP性能优化
1.前言 ABAP作为SAP的专用的开发语言,衡量其性能的指标主要有以下两个方面: 响应时间:对于某项特定的业务请求,系统在收到请求后需要多久返回结果 吞吐量:在给定的时间能,系统能够处理的数据量 2. ABAP语…...
【鸿蒙学习笔记】构建布局・选项卡 (Tabs)
官方文档:选项卡 (Tabs) 目录标题 底部导航顶部导航侧边导航限制导航栏的滑动切换固定导航栏・可滚动导航栏自定义导航栏切换至指定页签 底部导航 Entry Component struct Bujv_tabs {build() {Column() {Tabs({ barPosition: BarPosition.End }) {TabContent() {T…...
独立游戏《星尘异变》UE5 C++程序开发日志5——实现物流系统
目录 一、进出口清单 二、路径计算 三、包裹 1.包裹的数据结构 2.包裹在场景中的运动 四、道路 1.道路的数据结构 2.道路的建造 3.道路的销毁 4.某个有道路连接的建筑被删除 作为一个工厂类模拟经营游戏,各个工厂之间的运输必不可少,本游戏采用的…...
Web开发:<br>标签的作用
br作用 介绍基本用法常见用途注意事项使用CSS替代 介绍 在Web开发中,<br> 标签是一个用于插入换行符的HTML标签。它是“break”的缩写,常用于需要在文本中强制换行的地方。<br> 标签是一个空标签,这意味着它没有结束标签。 基本…...
DVC+Minio
由于参数文件比较大,因此onnx、engine等大文件弃用LFS管理,改用dvc管理: minio就是存储用的 启动miniosudo netstat -ntpl#查看端口号 sudo kill -9 $(sudo lsof -i:5061 -t) 关闭端口对应进程 ./minio server --console-address ":6570…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
