zoukankan      html  css  js  c++  java
  • Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件

    Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件

    1. 输入按键

    我们知道Android系统的按键分为三类:(1)Global Key;(2)System Key;(3)User Key

    • Global Key:按下一个按键,启动某个APP。 具体使用哪个按键启动哪个APP可以自己指定,修改frameworksasecore es esxmlGlobal_keys.xml,接下来有一篇博文具实现,假设它是AKEYCODE_TV

    • System Key:比如音量键(AKEYCODE_VOLUME_DOWN)

    • User Key:其他按键,比如ABCD(AKEYCODE_A)

    2. 回顾

    2.1 概述

    Reader线程把驱动上报的scancode根据.kl文件转化为keycode,Dispatch线程根据所获得keycode进行处理。Android Dispatch线程对这三类按键的处理

    * Global Key
    * System Key
    * User Key
    
    2.2 具体处理流程
    1. Reader线程将输入事件稍作处理
    2. Reader线程会将输入事件放入mInBoundQueue队列中
    3. Dispatch线程将从mInBoundQueue队列中取出输入事件,稍作处理
    4. 再将处理后的输入事件放入mOutBoundQueue队列
    5. 最后再从mOutBoundQueue队列中取出来,发给目的应用

    3. 阅读源码分析三种按键的处理过程

    之前已经分析了Reader线程从驱动程序得到扫描码之后,根据.KL文件,得到对应的按键码,然后构造args参数,接着使用NotifiyKey将该参数告诉Reader线程的Listener,而Reader线程的监听者肯定为Dispatch线程,要想验证,可以通过源代码分析得出。

    3.1 Golbal Key分析

    1. Reader线程获得他的Listener,调用notifykey做进一步的处理
    InputReader.cpp
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
    getListener()->notifyKey(&args);
    }
    
    2. 放入队列之前,稍作处理

    2.1 调用Java里面PhoneWindowManager的同名函数
    2.2 根据返回值设置policeFlags,对于global按键直接返回Pass_To_User

    InputDispatch.cpp
    //policyFlasgs接收函数的输出结果,根据policyFlags构造newEntry,将newEntry放入队列中
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
    
    3. 放入mInboundQueue队列
    InputDispatch.cpp
    needWake = enqueueInboundEventLocked(newEntry);
    
    4. 必要时候唤醒Dispatch线程
    InputDispatch.cpp
    if (needWake) {
        mLooper->wake();
    }
    

    3.2 System Key分析

    1. Reader线程获得他的Listener,调用notifykey做进一步的处理
    InputReader.cpp
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
    getListener()->notifyKey(&args);
    }
    
    2. 放入队列之前,稍作处理

    2.1 调用Java里面PhoneWindowManager的同名函数,分类处理

    • 可以处理的紧急事件,处理他,设置返回值为:!Pass_to_user
    • 返回pass_to_user
    InputDispatch.cpp
    //policyFlasgs接收函数的输出结果,根据policyFlags构造newEntry,将newEntry放入队列中
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
    
    3. 放入mInboundQueue队列
    InputDispatch.cpp
    needWake = enqueueInboundEventLocked(newEntry);
    
    4. 必要时候唤醒Dispatch线程
    InputDispatch.cpp
    if (needWake) {
        mLooper->wake();
    }
    

    3.3 User Key分析

    1. Reader线程获得他的Listener,调用notifykey做进一步的处理
    InputReader.cpp
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
    getListener()->notifyKey(&args);
    }
    
    2. 放入队列之前,稍作处理

    2.1 调用Java里面PhoneWindowManager的同名函数
    2.2 根据返回值设置policyFlags,对于用户按键直接返回Pass_To_User

    InputDispatch.cpp
    //policyFlasgs接收函数的输出结果,根据policyFlags构造newEntry,将newEntry放入队列中
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
    
    3. 放入mInboundQueue队列
    InputDispatch.cpp
    needWake = enqueueInboundEventLocked(newEntry);
    
    4. 必要时候唤醒Dispatch线程
    InputDispatch.cpp
    if (needWake) {
        mLooper->wake();
    }
    

    4. DIspatch流程修订图

    从上文分析可知,不论是否Pass_to_user,最终都要放入到队列mInboundQueue当中去,上篇博客总结的流程图有点错误,故进行修改,具体如下图。

  • 相关阅读:
    全面质量管理-质量管理水平(二)
    全面质量管理-质量管理历史发展概述(一)
    浅谈性能测试流程
    git本地分支与远程分支关联与解除关联
    Sourcetree 代码管理
    HttpRunner3.x 学习8-参数化数据驱动
    HttpRunner3.x 学习6-hook机制
    PHP =>和->区别
    FineBI:实现仪表板分享
    椭圆型方程网格生成法
  • 原文地址:https://www.cnblogs.com/lkq1220/p/7156771.html
Copyright © 2011-2022 走看看