Android 4.0中按键的处理流程

时间:2023-02-15 16:17:27

分类: android 202人阅读 评论(0) 收藏 举报 android4.0 按键消息响应流

1.开始肯定先说的是驱动这块,硬件是软件服务的,在Android这块C和java交互,有两种方式:

  1.1:驱动--JNI--服务-事件分发-上层应用处理。

  1.2:上层直接调用通过lib库的方式实现,中间使用回调机制,这种方式在Camera中有,下次再详解。

   先来看一下驱动按键映射部分的详解如下:

   映射实际是由KeyLayoutMap::map完成的,KeyLayoutMap类里读取配置文件qwerty.kl,由配置 文件 qwerty.kl决定键值的映射关系。你可以通过修改./development/emulator/keymaps/qwerty.kl来改变键值的映射关系。
  在frameworks/base/services/jni/com_android_server_KeyInputQueue.cpp文件中,向JAVA提供了函数android_server_KeyInputQueue_readEvent,用于读取输入设备事件。

  1. static jboolean  
  2. android_server_KeyInputQueue_readEvent(JNIEnv* env,jobject clazz,   
  3.                                           jobject event)   
  4. {   
  5.     gLock.lock();   
  6.     sp hub = gHub;   
  7.     if(hub == NULL) {  
  8.         hub = new EventHub;  
  9.         gHub = hub;   
  10.     }   
  11.     gLock.unlock();   
  12.   
  13.     int32_t deviceId;   
  14.     int32_t type;   
  15.     int32_t scancode, keycode;  
  16.     uint32_t flags;   
  17.     int32_t value;   
  18.     nsecs_t when;   
  19.     boolres = hub->getEvent(&deviceId,&type, &scancode,&keycode,  
  20.             &flags, &value,&when);  
  21.   
  22.     env->SetIntField(event, gInputOffsets.mDeviceId,(jint)deviceId);   
  23.     env->SetIntField(event, gInputOffsets.mType,(jint)type);   
  24.     env->SetIntField(event, gInputOffsets.mScancode,(jint)scancode);   
  25.     env->SetIntField(event, gInputOffsets.mKeycode,(jint)keycode);   
  26.     env->SetIntField(event, gInputOffsets.mFlags,(jint)flags);   
  27.     env->SetIntField(event, gInputOffsets.mValue,value);   
  28.     env->SetLongField(event, gInputOffsets.mWhen,  
  29.                         (jlong)(nanoseconds_to_milliseconds(when)));  
  30.   
  31.     returnres;   
  32.  

 2.下面要讲重头代码WindowManagerService.java(frameworks\base\services\java\com\android\server),这个服务有承上启下的作用,读取用户输入的信息,是通过创建一个InputDeviceReader线程,KeyQ构建时,会启动一个线程去读取用户消息,具体代码在KeyInputQueue.mThread,在构造函数中,mThread会start,接下来,接研究一下mThread.run:
   //用户输入事件消息读取线程
    ThreadmThread = new Thread("InputDeviceReader") {
       public void run() {
           RawInputEvent ev = new RawInputEvent();
           while (true) {//开始消息读取循环
               try {
                   InputDevice di;
                   //本地方法实现,读取用户输入事件
                   readEvent(ev);
                   //根据ev事件进行相关处理
                   ...
                   synchronized (mFirst) {//mFirst是keyQ队列头指针
                   ...
                   addLocked(di, curTimeNano,ev.flags,RawInputEvent.CLASS_TOUCHSCREEN, me);
                   ...
                   }