主要原因是和导航栏和屏幕最下方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. }

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

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标志。

android O 打开设置->声音->“点按时震动问题”的更多相关文章

  1. Android判断网络是否打开,并打开设置网络界面

    由于Android的SDK版本不同所以里面的API和设置方式也是有少量变化的,尤其是在Android 3.0 及后面的版本,UI和显示方式也发生了变化,现在就以打开网络设置为例,同大家分享一下: 1. ...

  2. Android 情景模式设置

    情景模式的设置大家应当相当熟悉了,但是在Android中如何通过自己的程序进行情景模式的设置呢,情景模式分为多种多种,即可以使用系统自带的,也可 以使用自定义的,但是在开发某些程序时,可能需要在程序中 ...

  3. 【转】Android 当打开“开发者模式”中的“不保留活动”后,程序应当怎么保持正常运行

    当打开这个设置以后,程序的Activity会自动销毁,每次返回的时候就会不断重oncreate,此时伴随的问题多多. 参考文档:http://www.bubuko.com/infodetail-960 ...

  4. eclipse的android智能提示设置

    eclipse的android智能提示设置 分类: android 技术2011-12-07 23:13 3069人阅读 评论(0) 收藏 举报 eclipseandroidtriggersjavaf ...

  5. Xamarin.Android 入门之:Android API版本设置

    一.引言 Xamarin.Android有几个Android API级别设置,确定多个版本的Android应用程序的兼容性.本博客解释了这些设置意味着什么,如何配置它们,以及它们在运行时对您的应用程序 ...

  6. Android 当打开“开发人员模式”中的“不保留活动”后,程序应当怎么保持正常执行

    Android 当打开"开发人员模式"中的"不保留活动"后,程序应当怎么保持正常执行咧. .? 在这几天,我一直在纠结这个问题.从发现,程序出现这个问题,是由于 ...

  7. react-native 打开设置界面

    iOS iOS打开设置还是比较简单的,使用Linking组件即可: Linking.openURL('app-settings:') .catch(err => console.log('err ...

  8. 【转】Android中通知的提示音、震动和LED灯效果小例子

    通知(Notification)是 Android 系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现.发出一条通知后,手机最上方 ...

  9. android intent打开各种文件的方法

    android intent打开各种文件的方法   1./**  * 检测是否安装了某个软件  *   * @param pkgName "com.bill99.kuaishua" ...

随机推荐

  1. 【20190407】JavaScript-indexOf方法解析

    在JavaScript中,字符串类型String和数组类型Array都有indexOf()方法,虽然他们的作用都是返回传入元素在指定字符串或数组中的位置,但他们之间还是存在着一点点不同. Str.in ...

  2. 四大机器学习编程语言对比:R、Python、MATLAB、Octave

    本文作者是一位机器学习工程师,他比较了四种机器学习编程语言(工具):R.Python.MATLAB 和 OCTAVE.作者列出了这些语言(工具)的优缺点,希望对想开始学习它们的人有用. 图源:Pixa ...

  3. 美团技术沙龙01 - 58到家服务的订单调度&数据分析技术

    1. 2015.4.15 到家服务的订单调度&数据分析技术 58到家· 黄海斌 @xemoaya 2.agenda • 58到家介绍 • 订单管理系统介绍 • 数据分析技术的应用 3.2015 ...

  4. 手机Soc芯片简介

    手机SoC(System On a Chip,在一个芯片里面集成CPU.GPU.SP.ISP.RAM内存.Wi-Fi控制器.基带芯片以及音频芯片等)芯片(基于arm架构指令集) 高通骁龙(Snapdr ...

  5. Spark之Yarn提交模式

    一.Client模式 提交命令: ./spark-submit --master yarn --class org.apache.examples.SparkPi ../lib/spark-examp ...

  6. SQLServer无法删除登录名'***',因为该用户当前正处于登录状态解决方法

    问题描述: sqlserver在删除登录名的时候提示删除失败 标题: Microsoft SQL Server Management Studio -------------------------- ...

  7. Redis可视化工具 Redis Desktop Manager

    1.前言 从接触Redis也有两年,平时就使用它来做缓存层,它给我的印象就是很强大,内置的数据结构很齐全,加上Redis5.0的到来,新增了很多特色功能.而Redis5.0最大的新特性就是多出了一个数 ...

  8. java-----理解java的三大特性之多态

    的java提高篇(四)-----理解的java的三大特性之多态 面向对象编程有三大特性:封装,继承,多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外 ...

  9. 聚类——GMM

    聚类——认识GMM算法 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 一.GMM概述 二.GMM算法步骤 三.具体推导参考文献 1. 李航. 统计学习 ...

  10. spring mybatics

    spring boot     web.mysql.mybatics.jps 遇到jar包版本不行的直接换个版本Add进去 https://github.com/forezp/SpringBootLe ...