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标志。
  • 相关阅读:
    7月的尾巴,你是XXX
    戏说Android view 工作流程《下》
    “燕子”
    Android开机动画bootanimation.zip
    戏说Android view 工作流程《上》
    ViewController里已连接的IBOutlet为什么会是nil
    My first App "Encrypt Wheel" is Ready to Download!
    iOS开发中角色Role所产生的悲剧(未完)
    UIScrollView实现不全屏分页的小技巧
    Apple misunderstood my app,now my app status changed to “In Review”
  • 原文地址:https://www.cnblogs.com/wangym/p/9483791.html
Copyright © 2011-2022 走看看