一、Android底层按键事件处理过程 在系统启动后,在文件。。。中,android 会通过 static const char *device_path = "/dev/input";
bool EventHub::penPlatformInput(void)
res = scan_dir(device_path); 通过下面的函数打开设备。
int EventHub::pen_device(const char *deviceName)
{
...
fd = open(deviceName, O_RDWR);
...
mFDs[mFDCount].fd = fd;
mFDs[mFDCount].events = POLLIN;
...
ioctl(mFDs[mFDCount].fd, EVIOCGNAME(sizeof(devname)-1), devname);
...
const char* root = getenv("ANDROID_ROOT");
snprintf(keylayoutFilename, sizeof(keylayoutFilename),
"%s/usr/keylayout/%s.kl", root, tmpfn);
...
device->layoutMap->load(keylayoutFilename);
...
} 打开设备的时候,如果 device->classes&CLASS_KEYBOARD 不等于 0 表明是键盘。
常用输入设备的定义有:
enum {
CLASS_KEYBOARD = 0x00000001, //键盘
CLASS_ALPHAKEY = 0x00000002, //
CLASS_TOUCHSCREEN = 0x00000004, //触摸屏
CLASS_TRACKBALL = 0x00000008 //轨迹球
}; 打开键盘设备的时候通过上面的 ioctl 获得设备名称,命令字 EVIOCGNAME 的定义在文件: kernel/include/linux/input.h 中。
对于按键事件,调用mDevices->layoutMap->map进行映射,调用的是文件 KeyLayoutMap.cpp (frameworks\base\libs\ui)中的函数:
status_t KeyLayoutMap::load(const char* filename)通过解析 <Driver name>.kl 把按键的 映射关系保存在 :KeyedVector<int32_t,Key> m_keys; 中。 当获得按键事件以后调用: status_t KeyLayoutMap::map(int32_t scancode, int32_t *keycode, uint32_t *flags)
由映射关系 KeyedVector<int32_t,Key> m_keys 把扫描码转换成andorid上层可以识别的按键。
二、按键映射 Key layout maps的路径是 /system/usr/keylayout,第一个查找的名字是按键驱动的名字,例如 mxckpd.kl。如果没有的话,默认为qwerty.kl。
Key character maps的路径是 /system/usr/keychars,第一个查找的名字是按键驱动的名字,例如 mxckpd.kcm。如果没有的话,默认为qwerty.kl。

qwerty.kl是 UTF-8类型的,格式为:key SCANCODE KEYCODE [FLAGS...]。

SCANCODE表示按键扫描码;
KEYCODE表示键值,例如HOME,BACK,1,2,3...
FLAGS有如下定义:
SHIFT: While pressed, the shift key modifier is set
ALT: While pressed, the alt key modifier is set
CAPS: While pressed, the caps lock key modifier is set
WAKE: When this key is pressed while the device is asleep, the device will wake up and the key event gets sent to the app.
WAKE_DROPPED: When this key is pressed while the device is asleep, the device will wake up and the key event does not get sent to the app

qwerty.kcm文件为了节省空间,在编译过程中会用工具makekcharmap转化为二进制文件qwerty.bin。 三、按键分发 1、输入事件分发线程

在frameworks/base/services/java/com/android/server/WindowManagerService.java里创 建了一个输入事件分发线程,它负责把事件分发到相应的窗口上去。

在WindowManagerService类的构造函数WindowManagerService()中:
mQueue = new KeyQ();//读取按键
mInputThread = new InputDispatcherThread(); //创建分发线程
...
mInputThread.start();

在启动的线程InputDispatcherThread中:
run()
process();
QueuedEvent ev = mQueue.getEvent(...)

在process() 方法中进行处理事件:
switch (ev.classType)
case RawInputEvent.CLASS_KEYBOARD:
...
dispatchKey((KeyEvent)ev.event, 0, 0);
mQueue.recycleEvent(ev);
break;
case RawInputEvent.CLASS_TOUCHSCREEN:
//Log.i(TAG, "Read next event " + ev);
dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
break;
  case RawInputEvent.CLASS_TRACKBALL:
dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
break;

2、上层读取按键的流程 WindowManagerService() //(frameworks\base\services\java\com\android\server \WindowManagerService.java)
|
KeyQ()//KeyQ 是抽象类 KeyInputQueue 的实现
|
InputDeviceReader//在 KeyInputQueue 类中创建的线程
|
readEvent()//
|
android_server_KeyInputQueue_readEvent()//frameworks\base\services\jni\ com_android_server_KeyInputQueue.cpp
|
hub->getEvent()
|
EventHub::getEvent()//frameworks\base\libs\ui\EventHub.cpp
|
res = read(mFDs.fd, &iev, sizeof(iev));//

更多相关文章

  1. Android:Deprecated Thread methods are not supported
  2. Android(安卓)实现定时任务的五种方式
  3. Android(安卓)系统服务 - Input 事件的分发过程
  4. Android为菜单添加事件
  5. Android解析WindowManagerService(一)WMS的诞生
  6. Android之Input子系统事件分发流程
  7. android官网图像与动画章节demo的分析
  8. Android(安卓)Button
  9. Android(安卓)Studio中Edittext监听回车事件,捕获手机和扫描枪的

随机推荐

  1. No private recovery resources for TARG
  2. Android中fill_parent、match_parent和wr
  3. Android ListView等getView调用多次问题
  4. Android 获得屏幕宽高的三种方式
  5. Android 球形进度条,动态控制时间与最大
  6. android 修改输入法中拼写检测默认值
  7. 进入页面后不弹出软键盘
  8. [置顶] android俄罗斯方块完整代码
  9. android获取inflater
  10. ContentResolver的使用