Android .kl按键布局文件
1.介绍
一个硬件按键的处理流程大致为:当用户按下或释放一个键时,键盘硬件会生成一个扫描码scan code,然后操作系统读取这个scan code,并将scan code扫描码映射到虚拟键码key code,最后操作系统根据映射的keycode生成输入事件,并将这些事件传递给应用程序或系统服务,进而执行相应的操作。
scan code和key code通过Key layout file 映射,Key layout file一般用于定义物理键盘上各个键的功能和映射关系。文件通常以 .kl 为后缀,例如我们熟知的 Generic.kl文件。
2.scan code和key code
先来介绍下scan code和key code:
scan code:扫描码,用于表示物理键盘或其他输入设备上按键的唯一标识符。scan code是硬件级别的编码,用于告诉操作系统哪个键被按下。
key code:键码,是操作系统层面上用于识别和处理输入事件的编码,可以将硬件层面的按键映射到更高层次的抽象,使得应用程序能够处理输入事件而不必直接关心底层硬件的细节。key code定义在KeyEvent.java中,一些常见的按键:
public static final int KEYCODE_DPAD_UP = 19;//方向上键的keycode为19public static final int KEYCODE_DPAD_DOWN = 20;//方向下键public static final int KEYCODE_DPAD_LEFT = 21;//方向左键public static final int KEYCODE_DPAD_RIGHT = 22;//方向右键public static final int KEYCODE_DPAD_CENTER = 23;//中间键
3.按键声明
按键映射关系声明在kl文件内,下面以一些常见的按键声明来说明它的语法规则:
frameworks/base/data/keyboards/Generic.klkey 103 DPAD_UP
key 104 PAGE_UP
key 105 DPAD_LEFT
key 106 DPAD_RIGHT
key 465 ESCAPE FUNCTION
按键声明包含关键字 key(后跟一个 Linux 按键代码编号和 Android 按键代码名称),任何一项声明都可以后跟一组由空格分隔的可选 flag。
常见的 flag:
FUNCTION:按键应解读为如同也按下了 FUNCTION 键。
GESTURE:按键由用户手势(例如手掌摸触摸屏)生成。
VIRTUAL:按键是与主触摸屏相邻的虚拟软键(电容式按钮)。这会导致启用特殊的去抖动逻辑
上述例子表明:scan code为103映射KeyEvent上的KEYCODE_DPAD_UP(后面以此类推)。
4.位置
按键布局文件由 USB vendor、product(可能还包括version)ID 或输入设备名称来确定位置。系统会按顺序查阅以下路径:
/odm/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/vendor/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/odm/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
/vendor/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
/system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl
/odm/usr/keylayout/DEVICE_NAME.kl
/vendor/usr/keylayout/DEVICE_NAME.kl
/system/usr/keylayout/DEVICE_NAME.kl
/data/system/devices/keylayout/DEVICE_NAME.kl
/odm/usr/keylayout/Generic.kl
/vendor/usr/keylayout/Generic.kl
/system/usr/keylayout/Generic.kl
/data/system/devices/keylayout/Generic.kl
5.Generic.kl
系统提供了一个常规按键布局文件,名为 Generic.kl。此按键布局旨在支持各种标准外部键盘和操纵杆,一般情况下不要轻易修改这个文件。
6.自定义kl文件
Android支持为硬件设备自定义kl文件,kl文件的定制需要遵循一定的规则,以帮助系统和开发者区分不同的硬件设备或输入设备。
命名规则:
命名规则通常包括硬件的制造商(Vendor)、设备型号(Product)以及布局类型等信息,格式通常为:
Vendor_XXX_Product_XXX.kl
Vendor:代表设备的制造商或供应商。通常是一个厂商的标识符或名称的缩写。
Product:代表具体的硬件产品型号。这个部分通常与设备的具体型号相关联,帮助区分不同的硬件设备。例如:
某个厂商制造了一个键盘设备,厂商ID为 abcd,产品ID为 efgh,则键盘布局文件的命名可能是:
Vendor_abcd_Product_efgh.kl
除了基本的 Vendor、Product 形式外,一些设备可能会使用其他的命名约定来包含更多的信息,例如:
Vendor_1234_Product_5678_Layout1.kl:可能表示设备 5678 的布局1。
Vendor_1234_Product_5678_Pro.kl:可能表示设备 5678 的专业版布局。
目录和位置:
这些 .kl 文件通常存放在Android设备的系统目录中,例如 /system/usr/keylayout/。系统会根据这些文件的定义来正确处理与物理键盘相关的输入事件。
文件内容:
.kl 文件的内容包括键位定义和映射,和Generic.kl语法一致
如果没有可用的设备专属kl文件,则系统将使用默认Generic.kl文件。
7.加载流程
kl文件的加载流程主要是在EventHub.cpp里的openDeviceLocked()方法里进行的
frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::openDeviceLocked(const std::string& devicePath) {......// Load the key map.// We need to do this for joysticks too because the key layout may specify axes, and for// sensor as well because the key layout may specify the axes to sensor data mapping.status_t keyMapStatus = NAME_NOT_FOUND;if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK |InputDeviceClass::SENSOR)) {// Load the keymap for the device.keyMapStatus = device->loadKeyMapLocked();}......
}
调用loadKeyMapLocked()方法继续加载
frameworks/native/services/inputflinger/reader/EventHub.cpp
status_t EventHub::Device::loadKeyMapLocked() {return keyMap.load(identifier, configuration.get());
}
调用frameworks/native/libs/input/Keyboard.cpp里的load方法,用来加载和配置键盘映射
frameworks/native/libs/input/Keyboard.cpp
status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,const PropertyMap* deviceConfiguration) {// Use the configured key layout if available.if (deviceConfiguration) {//如果.idc文件里有指定使用的kl文件,则首先加载指定的文件std::optional<std::string> keyLayoutName =deviceConfiguration->getString("keyboard.layout");//根据keyboard.layout字段来获取指定的.kl文件if (keyLayoutName.has_value()) {//如果存在指定的kl文件status_t status = loadKeyLayout(deviceIdentifier, *keyLayoutName);//加载键盘布局if (status == NAME_NOT_FOUND) {//未找到对应名称的kl文件ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but ""it was not found.",deviceIdentifier.name.c_str(), keyLayoutName->c_str());}}std::optional<std::string> keyCharacterMapName =deviceConfiguration->getString("keyboard.characterMap");//根据keyboard.characterMap字段来获取字符映射表的名称,一般是以.kcm结尾的文件if (keyCharacterMapName.has_value()) {status_t status = loadKeyCharacterMap(deviceIdentifier, *keyCharacterMapName);//加载kcm文件。if (status == NAME_NOT_FOUND) {//未找到对应名称字符映射表ALOGE("Configuration for keyboard device '%s' requested keyboard character ""map '%s' but it was not found.",deviceIdentifier.name.c_str(), keyCharacterMapName->c_str());}}if (isComplete()) {//加载完成之后返回return OK;}}// Try searching by device identifier.if (probeKeyMap(deviceIdentifier, "")) {//通过设备标识符查找键盘映射,即查找对应目录下是否有自定义的kl文件return OK;}// Fall back on the Generic key map.// TODO Apply some additional heuristics here to figure out what kind of// generic key map to use (US English, etc.) for typical external keyboards.if (probeKeyMap(deviceIdentifier, "Generic")) {//如果没有找到合适的kl文件,返回Generic.kl文件return OK;}// Try the Virtual key map as a last resort.if (probeKeyMap(deviceIdentifier, "Virtual")) {//查找虚拟键盘return OK;}// Give up!ALOGE("Could not determine key map for device '%s' and no default key maps were found!",deviceIdentifier.name.c_str());return NAME_NOT_FOUND;//以上方式都找不到kl文件,查找失败
}
可以看出kl文件的加载遵循以下顺序:
(1)如果.idc文件里keyboard.layout何keyboard.characterMap有指定使用的kl、kcm文件,则首先加载指定的kl、kcm文件
(2)如果.idc文件里没有配置指定的kl文件,那么通过设备信息去查找kl文件,一般为Vendor_XXX_Product_XXX(_Version_XXX).kl文件
(3)如果上述两种情况都没有找到kl文件,那么加载默认的Generic.kl文件
(4)最后尝试加载虚拟键盘映射表
相关文章:
Android .kl按键布局文件
1.介绍 一个硬件按键的处理流程大致为:当用户按下或释放一个键时,键盘硬件会生成一个扫描码scan code,然后操作系统读取这个scan code,并将scan code扫描码映射到虚拟键码key code,最后操作系统根据映射的keycode生成…...

Java每日一练_模拟面试题6(JVM的GC过程)
一、JVM虚拟机组成 JVM五大内存区域:程序计数器,Java虚拟机栈,本地方法栈,java堆,方法区。 堆被划分为两个区域:年轻代(Young)、老年代(Tenured)。年轻代又被划分为三个区域:Eden、From Surviv…...

数据防泄密软件推荐|(6大数据防泄密软件推荐!)
很多朋友在后台私信,什么是数据防泄密软件,有哪些数据防泄密软件推荐。 今天小编将从定义出发,深入浅出地介绍这一技术的工作原理、应用场景以及实现方式。 一、什么是文档透明加密? 文档透明加密是一种在用户无感知的情况下对文…...
Codeforces 874 div3 A-G
A. Musical Puzzle 分析 每两个相邻的字母都要录制一段,开个set记录一下,然后输出set的大小 C代码: #include<iostream> #include<set> using namespace std; void solve(){int n;string s;cin>>n>>s;set<strin…...

暑期数据结构 空间复杂度
3.空间复杂度 空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。 空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟…...

【Android Studio】图标一键生成 Image Asset Studio(一键各机型适配图标生成工具-告别一个一个替换)
文章目录 方法一:原始替换方法二:Image Asset Studio 方法一:原始替换 https://blog.csdn.net/xzzteach/article/details/140821856 方法二:Image Asset Studio 自动替换所有机型图标...

C++ | Leetcode C++题解之第332题重新安排行程
题目: 题解: class Solution { public:unordered_map<string, priority_queue<string, vector<string>, std::greater<string>>> vec;vector<string> stk;void dfs(const string& curr) {while (vec.count(curr) &am…...
使用Python实现简单的网页爬虫:抓取网站标题
使用Python实现简单的网页爬虫:抓取网站标题 在当今数据驱动的时代,网络爬虫(Web Crawler)成为了获取和分析网络数据的重要工具。无论是数据科学、市场分析还是学术研究,爬虫都能帮助我们从互联网上提取有价值的信息。本文将介绍如何使用Python实现一个简单的爬虫,抓取某…...

视觉SLAM ch3—三维空间的刚体运动
如果对于某些线性代数的知识不太牢固,可以看一下我的另一篇博客,写了一些基础知识并推荐了一些视频。 旋转矩阵 单元所需的线代基础知识https://blog.csdn.net/Johaden/article/details/141023668 一、旋转矩阵 1.点、向量、坐标系 在数学中&…...

计算机毕业设计选题推荐-二手图书交易系统-Java/Python项目实战
✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

4.MySQL数据类型
目录 数据类型 编辑数值类型 tinyint类型 bit类型 float类型 decimal类型 字符串类型 char类型 varchar varchar和char的区别 日期和时间类型 数据类型 数值类型 说明一下:MySQL本身是不支持bool类型的,当把一个数据设置成bool类型时&#x…...

快递查询新纪元:一键批量获取多家快递物流详情
跨快递平台批量查询神器:一站式解决信息追踪难题——固乔快递查询助手 在电商行业日益繁荣的今天,快递服务已经成为连接买卖双方不可或缺的一环。然而,随着合作的快递公司日益增多,如何高效地管理和追踪不同平台的快递信息&#…...
docker部署redis和mongoDB
docker部署mongoDB redismongoDB redis # --requirepass指定redis连接时的密码 # --appendonly yes 开启reids的AOF功能 docker run --name redis -p 6379:6379 -d redis:5.0.14 redis-server --requirepass 1234 --appendonly yes# 以/etc/redis/redis.conf的配置信息启动red…...

了解LVS,配置LVS
项目一、LVS 1.集群Cluster Cluster: 集群是为了解决某个特定问题将堕胎计算机组合起来形成的单个系统 LB:负载均衡 HA:高可用 HPC:高性能计算 2.分布式 分布式是将一个请求分成三个部分,按照功能拆分,使用微服…...

目标检测综述文章解读——Object Detection in 20 Years: A Survey
论文:Object Detection in 20 Years: A Survey 作者:Zhengxia Zou, Keyan Chen, Zhenwei Shi, Yuhong Guo, Jieping Ye 链接:https://arxiv.org/abs/1905.05055 这是一篇关于目标检测综述性文章,自2019年5月第一次提交后ÿ…...
Android make_vbmeta_image的参数值定义
网上生成vbmeta_system.img的命令,分析下这些参数的赋值,key的路径 out/host/linux-x86/bin/avbtool make_vbmeta_image --algorithm SHA256_RSA2048 --key device/mediatek/system/common/key/rsa2048/oem_prvk.pem --padding_size 4096 --rollback_index 0 --...

代码规范 —— 并发编程规范
优质博文:IT-BLOG-CN 【1】【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。 说明: 资源驱动类、工具类、单例工厂类都需要注意。 【2】【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。…...
仪器仪表控制:pymeasure常用模块以及API
下面是对 pymeasure.experiment 模块中各类和方法的详细介绍,包括它们的功能和用法。 pymeasure.experiment 模块详细介绍 Experiment 类 Experiment 类是 Pymeasure 中用于定义和管理实验的核心类。它包含实验的设置、执行和数据记录等功能。 构造函数 class …...

如何理解openfoam案例里面的blockMesh文件里面的simpleGrading
总结: simpleGrading参数分为xyz三个方向。如果你想使得网格在某个方向上更密集,可以在simpleGrading中将该方向的渐变率设置为小于 1 .更稀疏则设置大于1. 一、案例 比如我这个爆炸案例: 对应的blockMeshDIct文件如下: // 定…...
算法竞赛的制胜法宝:被严重低估的位运算究竟有什么用?
大家好,我是干货哥。今天咱们来聊聊一个让很多人都忽略的神技——位运算。等等,你是不是已经准备关掉这篇文章了?你以为位运算只是计算机底层的鸡肋操作?你以为这些不过是编程语言里最基础、最无趣的东西?但真的是这样…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...

CTF show 数学不及格
拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 用IDA Pro 64 打开这个文件 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 根据题目…...