Android应用程序键盘(Keyboard)消息处理机制分析(7)
函数首先根据文件名来打开这个设备文件:
- fd = open(deviceName, O_RDWR);
系统中所有输入设备文件信息都保存在成员变量mDevicesById中,因此,先在mDevicesById找到一个空位置来保存当前打开的设备文件信息:
- mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
- if (mDevicesById[devid].seq == 0) {
- mDevicesById[devid].seq = 1<<SEQ_SHIFT;
- }
找到了空闲位置后,就为这个输入设备文件创建相应的device_t信息:
- mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
- if (mDevicesById[devid].seq == 0) {
- mDevicesById[devid].seq = 1<<SEQ_SHIFT;
- }
- new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
- new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
- if (new_mFDs == NULL || new_devices == NULL) {
- LOGE("out of memory");
- return -1;
- }
- mFDs = new_mFDs;
- mDevices = new_devices;
- ......
- device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
- if (device == NULL) {
- LOGE("out of memory");
- return -1;
- }
- device->fd = fd;
同时,这个设备文件还会保存在数组mFDs中:
- mFDs[mFDCount].fd = fd;
- mFDs[mFDCount].events = POLLIN;
- mFDs[mFDCount].revents = 0;
接下来查看这个设备是不是键盘:
- // Figure out the kinds of events the device reports.
- uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
- memset(key_bitmask, 0, sizeof(key_bitmask));
- LOGV("Getting keys...");
- if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
- // See if this is a keyboard. Ignore everything in the button range except for
- // gamepads which are also considered keyboards.
- if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
- sizeof_bit_array(BTN_DIGI))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
- sizeof_bit_array(KEY_MAX + 1))) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
- device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
- if (device->keyBitmask != NULL) {
- memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
- } else {
- delete device;
- LOGE("out of memory allocating key bitmask");
- return -1;
- }
- }
- }
如果是的话,还要继续进一步初始化前面为这个设备文件所创建的device_t结构体,主要就是把结构体device的classes成员变量的INPUT_DEVICE_CLASS_KEYBOARD位置为1了,以表明这是一个键盘。
如果是键盘设备,初始化工作还未完成,还要继续设置键盘的布局等信息:
- if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
- char tmpfn[sizeof(name)];
- char keylayoutFilename[300];
- // a more descriptive name
- device->name = name;
- // replace all the spaces with underscores
- strcpy(tmpfn, name);
- for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
- *p = '_';
- // find the .kl file we need for this device
- const char* root = getenv("ANDROID_ROOT");
- snprintf(keylayoutFilename, sizeof(keylayoutFilename),
- "%s/usr/keylayout/%s.kl", root, tmpfn);
- bool defaultKeymap = false;
- if (access(keylayoutFilename, R_OK)) {
- snprintf(keylayoutFilename, sizeof(keylayoutFilename),
- "%s/usr/keylayout/%s", root, "qwerty.kl");
- defaultKeymap = true;
- }
- status_t status = device->layoutMap->load(keylayoutFilename);
- if (status) {
- LOGE("Error %d loading key layout.", status);
- }
- // tell the world about the devname (the descriptive name)
- if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
- // the built-in keyboard has a well-known device ID of 0,
- // this device better not go away.
- mHaveFirstKeyboard = true;
- mFirstKeyboardId = device->id;
- property_set("hw.keyboards.0.devname", name);
- } else {
- // ensure mFirstKeyboardId is set to -something-.
- if (mFirstKeyboardId == 0) {
- mFirstKeyboardId = device->id;
- }
- }
- char propName[100];
- sprintf(propName, "hw.keyboards.%u.devname", device->id);
- property_set(propName, name);
- // 'Q' key support = cheap test of whether this is an alpha-capable kbd
- if (hasKeycodeLocked(device, AKEYCODE_Q)) {
- device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
- }
- // See if this device has a DPAD.
- if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
- device->classes |= INPUT_DEVICE_CLASS_DPAD;
- }
- // See if this device has a gamepad.
- for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
- if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
- device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
- break;
- }
- }
- LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
- device->id, name, propName, keylayoutFilename);
- }
到这里,系统中的输入设备文件就打开了。
Android应用程序键盘(Keyboard)消息处理机制分析(7)相关推荐
- Android系统中的Binder通信机制分析(7)- Java 层的 Binder 机制
声明 其实对于Android系统Binder通信的机制早就有分析的想法,记得2019年6.7月份Mr.Deng离职期间约定一起对其进行研究的,但因为我个人问题没能实施这个计划,留下些许遗憾- 文中参考 ...
- Android应用程序键盘(Keyboard)消息处理机制分析(3)
Step 15. Looper.pollOnce 这个函数定义在frameworks/base/libs/utils/Looper.cpp文件中,具体可以参考前面Android应用程序消息处理机制(L ...
- Android应用程序键盘(Keyboard)消息处理机制分析(12)
Step 12. InputChannel.openInputChannelPair 这个函数定义在frameworks/base/core/java/android/view/InputChanne ...
- Android应用程序线程消息循环模型分析(5)
从AsyncTask的实现可以看出,当我们第一次创建一个AsyncTask对象时,首先会执行下面静态初始化代码创建一个线程池sExecutor: private static final Bloc ...
- Android应用程序线程消息循环模型分析
出自:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是通过消息来驱动的,即在应用程序的主线程(UI ...
- 以下未发布-Android的多线程以及异步消息处理机制,android移动开发基础案例教程源码
1.Message: Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间进行数据交换.除了 what 字段,还可以使用 arg1 和 arg2 来携带整型数据,使用 ...
- Android应用程序键盘(Keyboard)消息处理机制分析(20)
Step 24. InputQueue.dispatchKeyEvent 这个函数定义在frameworks/base/core/java/android/view/InputQueue.java文件 ...
- Android应用程序键盘(Keyboard)消息处理机制分析(26)
Step 7. LocalWindowManager.removeViewImmediate 这个函数定义在frameworks/base/core/java/android/view/Window. ...
- Android应用程序键盘(Keyboard)消息处理机制分析(17)
Step 11. InputDispatcher.dispatchOnceInnerLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文 ...
- Android应用程序键盘(Keyboard)消息处理机制分析(14)
3. InputManager分发键盘消息给应用程序的过程分析 在分析InputManager分发键盘消息给应用程序的过程之前,我们先假设现在没有键盘事件发生,因此,InputManager中的Inp ...
最新文章
- 最近喜欢用markdown写笔记,贴个语法说明
- linux 新建用户_使用Xshell和Xftp连接管理Linux服务器
- 【数字信号处理】线性时不变系统 LTI “ 输入 “ 与 “ 输出 “ 之间的关系 ( 线性卷积起点定理 | 左边序列概念 | 推理 )
- 同一台电脑上使用两个 github 账号
- 轻松构建基于 Serverless 架构的小程序
- org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:no sessi
- 您将在下一个项目中使用JSF吗?
- LLRP 提供程序概述
- ffplay.c函数结构简单分析(画图)
- Android Studio 3.4功能
- Linux第二章:5.Xshell安装教程、使用Xshell6进行Linux远程登录
- mumu 模拟器连不上adb
- 开源项目CRMEB 任意文件下载漏洞分析
- Linux的FTP安装、使用和配置(FTP客户端管理工具)
- android七牛短视频sdk源码,使用七牛开发短视频
- 小米5 MIUI 10系统完全Root教程 (Root思想通用所有机型)
- Java包装类及自动装箱、拆箱
- mysql的主句与从句_从句和主句怎样区分?
- 没有人比我更懂集群调度器---之流行集群调度器综述
- 西电杨宗凯调研计算机学院,杨宗凯调研指导研究生工作:深化研究生教育改革...
热门文章
- C#编程:SqlCommand.Parameters.Add()方法的参数问题。
- IOS contentOffset该如何理解
- 23个超流行的jQuery相册插件收集
- Mac基础操作:在双显示器设置中将Dock保持在一个屏幕上以防止其移动的方法
- NTFS For Mac的兼容性问题
- Ubuntu 20.04 国内源
- iOS底层探索之多线程(八)—GCD源码分析(函数的同步性、异步性、单例)
- WebForm读取指定的config文件的内容
- 在高并发环境下Reids做缓存踩坑记录
- 从ELK到EFK演进