zoukankan      html  css  js  c++  java
  • android O 打开设置>声音>“点按时震动问题”

    主要原因是和导航栏和屏幕最下方3个按键的属性配置有关,因为在PhoneWindowManager中调用方法performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);会去判断policyFlags & WindowManagerPolicy.FLAG_VIRTUAL,policyFlags这一属性。

    下面介绍一下事件的处理流程:

    1.对象的创建

    InputManagerService的初始化

    InputDispatcher和InputReader对象,再调用initialize方法分别创建了与InputDispatcher和InputReader对应的线程InputDispatcherThread和InputReaderThread对象

    2.事件的传递

    RawEvent是待发出去的事件,InputReader经由QueueInputListener就可以关联到InputDispatch,最后由InputDispatch将事件处理或分发出去。

    1. InputManager::InputManager(  
    2.         const sp<EventHubInterface>& eventHub,  
    3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
    4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
    5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
    6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
    7.     initialize();  
    8. }  
    1. InputReader::InputReader(const sp<EventHubInterface>& eventHub,  
    2.         const sp<InputReaderPolicyInterface>& policy,  
    3.         const sp<InputListenerInterface>& listener) :  
    4.         mContext(this), mEventHub(eventHub), mPolicy(policy),  
    5.         mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),  
    6.         mConfigurationChangesToRefresh(0) {  
    7.     mQueuedListener = new QueuedInputListener(listener);  
    8.   
    9.     ...  
    10. }  

    InputManager里创建了InputDispatch和InputReader,就是在此时将这两者关联了起来。以mDispatcher为参数创建了InputReader,mDispatcher就是InputReader的实际监听者,那么InputReader一收到事件就要主动通知监听者mDispatcher把这个事件处理掉。

    2.1. InputReader

    InputReader会创建InputReaderThread线程,threadloop()返回true表示该线程会一直执行loopOnce(). 

    1. bool InputReaderThread::threadLoop() {  
    2.     mReader->loopOnce();  
    3.     return true;  
    4. }  
    1. void InputReader::loopOnce() {  
    2.   
    3.     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  
    4.   
    5.     { // acquire lock  
    6.         AutoMutex _l(mLock);  
    7.   
    8.         if (count) {  
    9.             processEventsLocked(mEventBuffer, count);  
    10.         }  
    11.   
    12.     } // release lock  
    13.   
    14.     // Flush queued events out to the listener.  
    15.     // This must happen outside of the lock because the listener could potentially call  
    16.     // back into the InputReader's methods, such as getScanCodeState, or become blocked  
    17.     // on another thread similarly waiting to acquire the InputReader lock thereby  
    18.     // resulting in a deadlock.  This situation is actually quite plausible because the  
    19.     // listener is actually the input dispatcher, which calls into the window manager,  
    20.     // which occasionally calls into the input reader.  
    21.     mQueuedListener->flush();  
    22. }  

    loopOnce()先用getEvents()从设备文件中读出事件数据,然后进行一些处理。这种处理包括根据事件的类型(EV_KEY, EV_ABS, EV_SW)使用不同的InputMapper来处理事件,最后将事件放到列队中。最后的flush()会调用监听者(实际上是InputDispatch)来处理掉列队中所有的事件。

    3. 事件的策略标志policyFlags

    Android里事件有许多标志,如flags, policyFlags, metaState等,其中policyFlags用于决定一个事件的策略行为。比如一些特殊按键POWER,VOLUME,HOME等的处理行为在上层策略上不同,就需要对policyFlags设置不同的标志位。

    frameworks/base/include/ui/Input.h 文件中定义了policyFlags所有的标志位。

    有两个地方会设置policyFlags:

    1. EventHub 对每个设备都有一个struct Device结构,每个Device又有自己的KeyMap。EventHub::openDeviceLocked()打开一个设备时会使用loadKeyMapLocked()加载并解析keylayout文件。关于keylayout可以看官方的说明 http://source.android.com/tech/input/key-layout-files.html

    比如 frameworks/base/data/keyboards/Generic.kl 这个文件中有:
    1. key 113   VOLUME_MUTE  
    2. key 114   VOLUME_DOWN  
    3. key 115   VOLUME_UP  
    4. key 116   POWER             WAKE  
     
    frameworks/base/libs/ui/KeyLayoutMap.cpp
    frameworks/base/include/ui/KeycodeLabels.h 
    1. // NOTE: If you edit these flags, also edit policy flags in Input.h.  
    2. static const KeycodeLabel FLAGS[] = {  
    3.     { "WAKE", 0x00000001 },  
    4.     { "WAKE_DROPPED", 0x00000002 },  
    5.     { "SHIFT", 0x00000004 },  
    6.     { "CAPS_LOCK", 0x00000008 },  
    7.     { "ALT", 0x00000010 },  
    8.     { "ALT_GR", 0x00000020 },  
    9.     { "MENU", 0x00000040 },  
    10.     { "LAUNCHER", 0x00000080 },  
    11.     { "VIRTUAL", 0x00000100 },  
    12.     { "FUNCTION", 0x00000200 },  
    13.     { NULL, 0 }  
    14. };  
    需要注意的是,在 frameworks/base/include/ui/Input.h 中定义了所有策略相关的标志,且需要和FLAGS[]里的值保持一致,不然就乱套了。

    EventHub::getEvents()读到一个事件之后,会从按照scancode从keylayout中得到相应的策略标志,此时记录于event->flags中。按下POWER键时,getEvents()收到的scanCode是116,再从keyMap中用扫一遍,POWER键有"WAKE"属性,则设置0x00000001标志位。
    1. if (iev.type == EV_KEY && device->keyMap.haveKeyLayout()) {  
    2.     status_t err = device->keyMap.keyLayoutMap->mapKey(iev.code,  
    3.                 &event->keyCode, &event->flags);  
    4.     LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",  
    5.             iev.code, event->keyCode, event->flags, err);  
    6. }  
     
    2. InputDispatcher 中也会再做一些判断来设置policyFlags标志。
  • 相关阅读:
    前 K 个高频元素
    lex与yacc(二)计算器的实现
    lex与yacc(二)计算器的实现
    python人工智能——机器学习——分类算法朴素贝叶斯算法对新闻进行分类案例
    python人工智能——机器学习——分类算法朴素贝叶斯算法对新闻进行分类案例
    python人工智能——机器学习——分类算法朴素贝叶斯算法
    python人工智能——机器学习——分类算法朴素贝叶斯算法
    python人工智能——机器学习——分类算法朴素贝叶斯算法
    PaddlePaddle训练营——公开课——AI核心技术掌握——第1章迈入现代人工智能的大门——深度学习简介
    PaddlePaddle训练营——公开课——AI核心技术掌握——第1章迈入现代人工智能的大门——深度学习简介
  • 原文地址:https://www.cnblogs.com/wangym/p/9483791.html
Copyright © 2011-2022 走看看