函数首先根据文件名来打开这个设备文件:

  1. fd = open(deviceName, O_RDWR);

系统中所有输入设备文件信息都保存在成员变量mDevicesById中,因此,先在mDevicesById找到一个空位置来保存当前打开的设备文件信息:

  1. mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
  2. if (mDevicesById[devid].seq == 0) {
  3. mDevicesById[devid].seq = 1<<SEQ_SHIFT;
  4. }

找到了空闲位置后,就为这个输入设备文件创建相应的device_t信息:

  1. mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
  2. if (mDevicesById[devid].seq == 0) {
  3. mDevicesById[devid].seq = 1<<SEQ_SHIFT;
  4. }
  5. new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
  6. new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
  7. if (new_mFDs == NULL || new_devices == NULL) {
  8. LOGE("out of memory");
  9. return -1;
  10. }
  11. mFDs = new_mFDs;
  12. mDevices = new_devices;
  13. ......
  14. device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
  15. if (device == NULL) {
  16. LOGE("out of memory");
  17. return -1;
  18. }
  19. device->fd = fd;

同时,这个设备文件还会保存在数组mFDs中:

  1. mFDs[mFDCount].fd = fd;
  2. mFDs[mFDCount].events = POLLIN;
  3. mFDs[mFDCount].revents = 0;

接下来查看这个设备是不是键盘:

  1. // Figure out the kinds of events the device reports.
  2. uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
  3. memset(key_bitmask, 0, sizeof(key_bitmask));
  4. LOGV("Getting keys...");
  5. if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
  6. // See if this is a keyboard.  Ignore everything in the button range except for
  7. // gamepads which are also considered keyboards.
  8. if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
  9. || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
  10. sizeof_bit_array(BTN_DIGI))
  11. || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
  12. sizeof_bit_array(KEY_MAX + 1))) {
  13. device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
  14. device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
  15. if (device->keyBitmask != NULL) {
  16. memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
  17. } else {
  18. delete device;
  19. LOGE("out of memory allocating key bitmask");
  20. return -1;
  21. }
  22. }
  23. }

如果是的话,还要继续进一步初始化前面为这个设备文件所创建的device_t结构体,主要就是把结构体device的classes成员变量的INPUT_DEVICE_CLASS_KEYBOARD位置为1了,以表明这是一个键盘。
        如果是键盘设备,初始化工作还未完成,还要继续设置键盘的布局等信息:

  1. if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
  2. char tmpfn[sizeof(name)];
  3. char keylayoutFilename[300];
  4. // a more descriptive name
  5. device->name = name;
  6. // replace all the spaces with underscores
  7. strcpy(tmpfn, name);
  8. for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
  9. *p = '_';
  10. // find the .kl file we need for this device
  11. const char* root = getenv("ANDROID_ROOT");
  12. snprintf(keylayoutFilename, sizeof(keylayoutFilename),
  13. "%s/usr/keylayout/%s.kl", root, tmpfn);
  14. bool defaultKeymap = false;
  15. if (access(keylayoutFilename, R_OK)) {
  16. snprintf(keylayoutFilename, sizeof(keylayoutFilename),
  17. "%s/usr/keylayout/%s", root, "qwerty.kl");
  18. defaultKeymap = true;
  19. }
  20. status_t status = device->layoutMap->load(keylayoutFilename);
  21. if (status) {
  22. LOGE("Error %d loading key layout.", status);
  23. }
  24. // tell the world about the devname (the descriptive name)
  25. if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
  26. // the built-in keyboard has a well-known device ID of 0,
  27. // this device better not go away.
  28. mHaveFirstKeyboard = true;
  29. mFirstKeyboardId = device->id;
  30. property_set("hw.keyboards.0.devname", name);
  31. } else {
  32. // ensure mFirstKeyboardId is set to -something-.
  33. if (mFirstKeyboardId == 0) {
  34. mFirstKeyboardId = device->id;
  35. }
  36. }
  37. char propName[100];
  38. sprintf(propName, "hw.keyboards.%u.devname", device->id);
  39. property_set(propName, name);
  40. // 'Q' key support = cheap test of whether this is an alpha-capable kbd
  41. if (hasKeycodeLocked(device, AKEYCODE_Q)) {
  42. device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
  43. }
  44. // See if this device has a DPAD.
  45. if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
  46. hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
  47. hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
  48. hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
  49. hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
  50. device->classes |= INPUT_DEVICE_CLASS_DPAD;
  51. }
  52. // See if this device has a gamepad.
  53. for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
  54. if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
  55. device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
  56. break;
  57. }
  58. }
  59. LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
  60. device->id, name, propName, keylayoutFilename);
  61. }

到这里,系统中的输入设备文件就打开了。

本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966619,如需转载请自行联系原作者

Android应用程序键盘(Keyboard)消息处理机制分析(7)相关推荐

  1. Android系统中的Binder通信机制分析(7)- Java 层的 Binder 机制

    声明 其实对于Android系统Binder通信的机制早就有分析的想法,记得2019年6.7月份Mr.Deng离职期间约定一起对其进行研究的,但因为我个人问题没能实施这个计划,留下些许遗憾- 文中参考 ...

  2. Android应用程序键盘(Keyboard)消息处理机制分析(3)

    Step 15. Looper.pollOnce 这个函数定义在frameworks/base/libs/utils/Looper.cpp文件中,具体可以参考前面Android应用程序消息处理机制(L ...

  3. Android应用程序键盘(Keyboard)消息处理机制分析(12)

    Step 12. InputChannel.openInputChannelPair 这个函数定义在frameworks/base/core/java/android/view/InputChanne ...

  4. Android应用程序线程消息循环模型分析(5)

      从AsyncTask的实现可以看出,当我们第一次创建一个AsyncTask对象时,首先会执行下面静态初始化代码创建一个线程池sExecutor: private static final Bloc ...

  5. Android应用程序线程消息循环模型分析

    出自:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是通过消息来驱动的,即在应用程序的主线程(UI ...

  6. 以下未发布-Android的多线程以及异步消息处理机制,android移动开发基础案例教程源码

    1.Message: Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间进行数据交换.除了 what 字段,还可以使用 arg1 和 arg2 来携带整型数据,使用 ...

  7. Android应用程序键盘(Keyboard)消息处理机制分析(20)

    Step 24. InputQueue.dispatchKeyEvent 这个函数定义在frameworks/base/core/java/android/view/InputQueue.java文件 ...

  8. Android应用程序键盘(Keyboard)消息处理机制分析(26)

    Step 7. LocalWindowManager.removeViewImmediate 这个函数定义在frameworks/base/core/java/android/view/Window. ...

  9. Android应用程序键盘(Keyboard)消息处理机制分析(17)

    Step 11. InputDispatcher.dispatchOnceInnerLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文 ...

  10. Android应用程序键盘(Keyboard)消息处理机制分析(14)

    3. InputManager分发键盘消息给应用程序的过程分析 在分析InputManager分发键盘消息给应用程序的过程之前,我们先假设现在没有键盘事件发生,因此,InputManager中的Inp ...

最新文章

  1. 最近喜欢用markdown写笔记,贴个语法说明
  2. linux 新建用户_使用Xshell和Xftp连接管理Linux服务器
  3. 【数字信号处理】线性时不变系统 LTI “ 输入 “ 与 “ 输出 “ 之间的关系 ( 线性卷积起点定理 | 左边序列概念 | 推理 )
  4. 同一台电脑上使用两个 github 账号
  5. 轻松构建基于 Serverless 架构的小程序
  6. org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:no sessi
  7. 您将在下一个项目中使用JSF吗?
  8. LLRP 提供程序概述
  9. ffplay.c函数结构简单分析(画图)
  10. Android Studio 3.4功能
  11. Linux第二章:5.Xshell安装教程、使用Xshell6进行Linux远程登录
  12. mumu 模拟器连不上adb
  13. 开源项目CRMEB 任意文件下载漏洞分析
  14. Linux的FTP安装、使用和配置(FTP客户端管理工具)
  15. android七牛短视频sdk源码,使用七牛开发短视频
  16. 小米5 MIUI 10系统完全Root教程 (Root思想通用所有机型)
  17. Java包装类及自动装箱、拆箱
  18. mysql的主句与从句_从句和主句怎样区分?
  19. 没有人比我更懂集群调度器---之流行集群调度器综述
  20. 西电杨宗凯调研计算机学院,杨宗凯调研指导研究生工作:深化研究生教育改革...

热门文章

  1. C#编程:SqlCommand.Parameters.Add()方法的参数问题。
  2. IOS contentOffset该如何理解
  3. 23个超流行的jQuery相册插件收集
  4. Mac基础操作:在双显示器设置中将Dock保持在一个屏幕上以防止其移动的方法
  5. NTFS For Mac的兼容性问题
  6. Ubuntu 20.04 国内源
  7. iOS底层探索之多线程(八)—GCD源码分析(函数的同步性、异步性、单例)
  8. WebForm读取指定的config文件的内容
  9. 在高并发环境下Reids做缓存踩坑记录
  10. 从ELK到EFK演进