当前位置: 首页 > news >正文

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.介绍 一个硬件按键的处理流程大致为&#xff1a;当用户按下或释放一个键时&#xff0c;键盘硬件会生成一个扫描码scan code&#xff0c;然后操作系统读取这个scan code&#xff0c;并将scan code扫描码映射到虚拟键码key code&#xff0c;最后操作系统根据映射的keycode生成…...

Java每日一练_模拟面试题6(JVM的GC过程)

一、JVM虚拟机组成 JVM五大内存区域&#xff1a;程序计数器&#xff0c;Java虚拟机栈&#xff0c;本地方法栈&#xff0c;java堆&#xff0c;方法区。 堆被划分为两个区域&#xff1a;年轻代(Young)、老年代(Tenured)。年轻代又被划分为三个区域&#xff1a;Eden、From Surviv…...

数据防泄密软件推荐|(6大数据防泄密软件推荐!)

很多朋友在后台私信&#xff0c;什么是数据防泄密软件&#xff0c;有哪些数据防泄密软件推荐。 今天小编将从定义出发&#xff0c;深入浅出地介绍这一技术的工作原理、应用场景以及实现方式。 一、什么是文档透明加密&#xff1f; 文档透明加密是一种在用户无感知的情况下对文…...

Codeforces 874 div3 A-G

A. Musical Puzzle 分析 每两个相邻的字母都要录制一段&#xff0c;开个set记录一下&#xff0c;然后输出set的大小 C代码&#xff1a; #include<iostream> #include<set> using namespace std; void solve(){int n;string s;cin>>n>>s;set<strin…...

暑期数据结构 空间复杂度

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

【Android Studio】图标一键生成 Image Asset Studio(一键各机型适配图标生成工具-告别一个一个替换)

文章目录 方法一&#xff1a;原始替换方法二&#xff1a;Image Asset Studio 方法一&#xff1a;原始替换 https://blog.csdn.net/xzzteach/article/details/140821856 方法二&#xff1a;Image Asset Studio 自动替换所有机型图标...

C++ | Leetcode C++题解之第332题重新安排行程

题目&#xff1a; 题解&#xff1a; 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—三维空间的刚体运动

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

计算机毕业设计选题推荐-二手图书交易系统-Java/Python项目实战

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

4.MySQL数据类型

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

快递查询新纪元:一键批量获取多家快递物流详情

跨快递平台批量查询神器&#xff1a;一站式解决信息追踪难题——固乔快递查询助手 在电商行业日益繁荣的今天&#xff0c;快递服务已经成为连接买卖双方不可或缺的一环。然而&#xff0c;随着合作的快递公司日益增多&#xff0c;如何高效地管理和追踪不同平台的快递信息&#…...

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&#xff1a;负载均衡 HA&#xff1a;高可用 HPC&#xff1a;高性能计算 2.分布式 分布式是将一个请求分成三个部分&#xff0c;按照功能拆分&#xff0c;使用微服…...

目标检测综述文章解读——Object Detection in 20 Years: A Survey

论文&#xff1a;Object Detection in 20 Years: A Survey 作者&#xff1a;Zhengxia Zou, Keyan Chen, Zhenwei Shi, Yuhong Guo, Jieping Ye 链接&#xff1a;https://arxiv.org/abs/1905.05055 这是一篇关于目标检测综述性文章&#xff0c;自2019年5月第一次提交后&#xff…...

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 --...

代码规范 —— 并发编程规范

优质博文&#xff1a;IT-BLOG-CN 【1】【强制】获取单例对象需要保证线程安全&#xff0c;其中的方法也要保证线程安全。 说明&#xff1a; 资源驱动类、工具类、单例工厂类都需要注意。 【2】【强制】创建线程或线程池时请指定有意义的线程名称&#xff0c;方便出错时回溯。…...

仪器仪表控制:pymeasure常用模块以及API

下面是对 pymeasure.experiment 模块中各类和方法的详细介绍&#xff0c;包括它们的功能和用法。 pymeasure.experiment 模块详细介绍 Experiment 类 Experiment 类是 Pymeasure 中用于定义和管理实验的核心类。它包含实验的设置、执行和数据记录等功能。 构造函数 class …...

如何理解openfoam案例里面的blockMesh文件里面的simpleGrading

总结&#xff1a; simpleGrading参数分为xyz三个方向。如果你想使得网格在某个方向上更密集&#xff0c;可以在simpleGrading中将该方向的渐变率设置为小于 1 .更稀疏则设置大于1. 一、案例 比如我这个爆炸案例&#xff1a; 对应的blockMeshDIct文件如下&#xff1a; // 定…...

算法竞赛的制胜法宝:被严重低估的位运算究竟有什么用?

大家好&#xff0c;我是干货哥。今天咱们来聊聊一个让很多人都忽略的神技——位运算。等等&#xff0c;你是不是已经准备关掉这篇文章了&#xff1f;你以为位运算只是计算机底层的鸡肋操作&#xff1f;你以为这些不过是编程语言里最基础、最无趣的东西&#xff1f;但真的是这样…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

【WebSocket】SpringBoot项目中使用WebSocket

1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖&#xff0c;添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...