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当中去,上篇博客总结的流程图有点错误,故进行修改,具体如下图。

  • 相关阅读:
    iOS 面试题搜集
    iOS 常用第三方类库、完整APP示例
    iOS 键盘遮挡输入 解决办法
    iOS UIColor RGB HEX
    iOS APP性能优化
    iOS Swift 数组 交换元素的两种方法
    iOS CoreData primitive accessor
    iOS Start developing ios apps (OC) pdf
    iOS 传值方式
    iOS IB_DESIGNABLE IBInspectable @IBDesignable @IBInspectable 加速UI开发
  • 原文地址:https://www.cnblogs.com/lkq1220/p/7156771.html
Copyright © 2011-2022 走看看