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

简介:

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

  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.   
  6. new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));  
  7. new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));  
  8. if (new_mFDs == NULL || new_devices == NULL) {  
  9.     LOGE("out of memory");  
  10.     return -1;  
  11. }  
  12. mFDs = new_mFDs;  
  13. mDevices = new_devices;  
  14.   
  15. ......  
  16.   
  17. device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);  
  18. if (device == NULL) {  
  19.     LOGE("out of memory");  
  20.     return -1;  
  21. }  
  22.   
  23. 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.   
  3. uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];  
  4. memset(key_bitmask, 0, sizeof(key_bitmask));  
  5.   
  6. LOGV("Getting keys...");  
  7. if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {  
  8.     // See if this is a keyboard.  Ignore everything in the button range except for  
  9.     // gamepads which are also considered keyboards.  
  10.     if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))  
  11.         || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),  
  12.         sizeof_bit_array(BTN_DIGI))  
  13.         || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),  
  14.         sizeof_bit_array(KEY_MAX + 1))) {  
  15.             device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;  
  16.   
  17.             device->keyBitmask = new uint8_t[sizeof(key_bitmask)];  
  18.             if (device->keyBitmask != NULL) {  
  19.                 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));  
  20.             } else {  
  21.                 delete device;  
  22.                 LOGE("out of memory allocating key bitmask");  
  23.                 return -1;  
  24.             }  
  25.     }  
  26. }  

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

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





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966619,如需转载请自行联系原作者
目录
打赏
0
0
0
0
235
分享
相关文章
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
578 4
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
211 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
69 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
127 14
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
187 21
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
77 8
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
深入探索Android与iOS的多任务处理机制
在移动操作系统领域,Android和iOS各有千秋,尤其在多任务处理上展现出不同的设计理念和技术实现。本文将深入剖析两大平台在后台管理、资源分配及用户体验方面的策略差异,揭示它们如何平衡性能与电池寿命,为用户带来流畅而高效的操作体验。通过对比分析,我们不仅能够更好地理解各自系统的工作机制,还能为开发者优化应用提供参考。
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
109 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等