【Android】WMS(五)输入事件原理

这篇具有很好参考价值的文章主要介绍了【Android】WMS(五)输入事件原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

输入事件原理

安卓输入事件整体流程

Android 系统是由事件驱动的,而 input 是最常见的事件之一,用户的点击、滑动、长按等操作,都属于 input 事件驱动,其中的核心就是 InputReader 和 InputDispatcher。

InputReader 和 InputDispatcher 是跑在 SystemServer进程中的两个 native 循环线程,负责读取和分发 Input 事件。整个处理过程大致流程如下:

【Android】WMS(五)输入事件原理

InputManagerService

在SystemServer的startOtherServices函数中,会新建一个InputManagerService对象,然后会作为参数传入到WMS中去。

inputManager = new InputManagerService(context);
......
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
WindowInputEventReceiver输入事件监听

在ViewRootImpl的setView函数中,会先建立一个InputChannel对象。inputChannel是输入事件的信道,它ViewRootImpl和InputManagerService的沟通桥梁。

 InputChannel inputChannel = null;
 if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
      inputChannel = new InputChannel();
 }

inputChannel会通过mWindowSession.addToDisplayAsUser方法传入到WMS侧,并且与当前新建窗口WindowState建立起关系

if  (openInputChannels) {
	//WindowState与InputChannel关联上了
    win.openInputChannel(outInputChannel);
}

之后代码运行到ViewRootImpl侧,这个时候就开始生成监听对象

if (inputChannel != null) {
                    if (mInputQueueCallback != null) {
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
   					// 输入事件的监听对象
                    mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
                            Looper.myLooper());
                }

}
EventHub设备事件监听

它主要是利用Linux的inotify和epoll机制,监听设备事件:包括设备插拔及各种触摸、按钮事件等,可以看做是一个不同设备的集线器,主要面向的是/dev/input目录下的设备节点,比如说/dev/input/event0上的事件就是输入事件:

【Android】WMS(五)输入事件原理

InputReader读取事件

InputReader主要是负责不断的从EventHub读取事件,通知派发给InputDispatcher。

void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    std::vector<InputDeviceInfo> inputDevices;
    { 
    ......
    // 读取EventHub中的事件
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
   ......
   // 通知派发给InputDispatcher
   mQueuedListener->flush();
}
InputDispatcher读取事件
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        ......
        // 被唤醒 ,处理Input消息
        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;
        }
    
       .....
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    //睡眠等到事件
    mLooper->pollOnce(timeoutMillis);
}
寻找目标窗口

Android系统能够同时支持多块屏幕,每块屏幕被抽象成一个DisplayContent对象,内部维护一个WindowList列表对象,用来记录当前屏幕中的所有窗口,包括状态栏、导航栏、应用窗口、子窗口等。对于触摸事件,我们比较关心可见窗口

那么,如何找到触摸事件对应的窗口呢,是状态栏、导航栏还是应用窗口呢,这个时候DisplayContent的WindowList就发挥作用了,DisplayContent握着所有窗口的信息,因此,可以根据触摸事件的位置及窗口的属性来确定将事件发送到哪个窗口,当然其中的细节比一句话复杂的多,跟窗口的状态、透明、分屏等信息都有关系,下面简单瞅一眼,达到主观理解的流程就可以了,然后会调用到InputDispatcher#findTouchedWindowAtLocked

// 遍历所有窗口 
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
        const InputWindowInfo* windowInfo = windowHandle->getInfo();
        if (windowInfo->displayId == displayId) {
            int32_t flags = windowInfo->layoutParamsFlags;

            if (windowInfo->visible) {
                if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
                    bool isTouchModal = (flags &
                                         (InputWindowInfo::FLAG_NOT_FOCUSABLE |
                                          InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
                        int32_t portalToDisplayId = windowInfo->portalToDisplayId;
                        ......
                        // Found window. 找到目标窗口
                        return windowHandle;
                    }
                }
            }
        }

mWindowHandles代表着所有窗口,找到了目标窗口,同时也将事件封装好了,剩下的就是通知目标窗口,可是有个最明显的问题就是,目前所有的逻辑都是在SystemServer进程,而要通知的窗口位于APP端的用户进程,那么如何通知呢?这里面采用的都是Socket的通信方式。文章来源地址https://www.toymoban.com/news/detail-476968.html

到了这里,关于【Android】WMS(五)输入事件原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android WMS——Window窗口(三)

            Window 是一个窗口的概念,是所有视图的载体,不管是 Activity,Dialog,还是 Toast,他们的视图都是附加在 Window 上面的。例如在桌面显示一个悬浮窗,就需要用到 Window 来实现。 WindowManager 是访问 Window 的入口。         Window 类是一个抽象类,他的实现类是 Phon

    2024年02月07日
    浏览(37)
  • android display 杂谈(三)WMS

    用来记录学习wms,后续会一点一点更新。。。。。。 代码:android14 WMS是在SystemServer进程中启动的 在SystemServer中的main方法中,调用run方法。 android14中,在startOtherServices中启动WindowManagerService 该代码执行了WMS的main方法,会在内部创建一个WMS。其中有一个参数inputManager也是在

    2024年02月05日
    浏览(42)
  • Android T WMS窗口相关流程

    什么是窗口 窗口即是屏幕上的一块用于绘制各种UI元素并可以响应用户输入的一个矩形区域。从原理上讲,窗口的概念是独自占有一个Surface实例的显示区域(我们在屏幕上看到的图形都需要绘制在Surface上)。 Window是个抽象类其实现类为PhoneWindow。 本文以窗口添加的流程为例

    2024年02月03日
    浏览(50)
  • 【Android】WMS(二)Window的添加

    在 Android 应用开发中,软键盘的显示与隐藏是一个经常出现的问题,而 WindowManager 的 LayoutParams 中定义的软键盘相关模式则为开发者提供了一些解决方案。 其中, SoftInputMode 就是用于描述软键盘的显示方式和窗口的调整方式的属性。常用的几个 SoftInputMode 的作用: SOFT_INPUT_

    2024年02月09日
    浏览(52)
  • Android14 WMS 窗口布局流程performSurfacePlacement

    在WMS启动的时候,就创建了WindowSurfacePlacer对象,该对象专门用来执行窗口Surface的“摆放”操作。 标题      WindowSurfacePlacer#performSurfacePlacement() 方法,可以说是WMS中最核心的方法,负责所有窗口的Surface的摆放工作,如何显示、显示在什么位置、显示区域多大,都将通过这个

    2024年04月14日
    浏览(38)
  • systemserver的inputdispatcher直接产生CANCEL事件原理分析-讨厌的android触摸面试题

    上一个blog已经重点讲解了app层面自己产生的Cancel触摸事件,大概产生的原理如下: 上一个blog地址:https://blog.csdn.net/learnframework/article/details/124086882 即可以看出来,在服务端systemserver其实传递的触摸事件依然是move,只是move事件到了app端后,由于app端自己的业务把这个传递的

    2024年02月09日
    浏览(44)
  • Android 关于View事件分发(onTouch、onTouchEvent、onClick、onLongClick的关系及原理)(一)

    事件 含义 ACTION_DOWN 手指初次碰到屏幕时触发 ACTION_MOVE 手指在屏幕上滑动时触发(ps:会多次触发,看源码时同一块代码应该看多次去理解) ACTION_UP 手指离开屏幕时触发 ACTION_CANCEL 事件被上层拦截时触发   关于ACTION_MOVE事件,手指在屏幕上滑动时会触发多次,对于这个点,看源码

    2024年01月24日
    浏览(40)
  • 【Android】WMS(三)Window的更新&UI刷新

    在 Android 中,窗口的更新是一个非常常见的事情。比如,在使用 App 过程中,需要弹出键盘窗口或者切换横竖屏时,就会发生窗口的更新。 首先,当需要更新窗口时,会调用 WindowManager 的 updateViewLayout() 方法来设置参数,并将参数设置到 对应的 View 上。WindowManager 的实现类为

    2024年02月09日
    浏览(77)
  • android 13 WMS/AMS系统开发-窗口层级相关DisplayArea,WindowContainer

    官方注释: 给可以直接持有窗口的自己或它的孩子定义了一些公共的方法和属性,像RootWindowContainer、DisplayContent、DisplayArea、DisplayArea.Tokens、TaskDisplayArea、Task、ActivityRecord、WindowToken、WindowState都是直接或间接的继承该类。 这里面主要的重要要成员变量就是mParent和mChildren,一

    2024年02月16日
    浏览(40)
  • Android Framework最难模块WMS实战作业-手机车机系统开发必备

    0-整体介绍 1-window-container.mp4 窗口层级树实战启动篇 2-displayarea-feature.mp4 窗口层级树源码分析相关 3-displayarea-draw-feature.mp4 窗口层级树绘制实战1 4-displayarea-draw-leaf.mp4 窗口层级树绘制实战2 5-displayarea-draw-leaf-2.mp4 窗口层级树绘制实战3 6-displayarea-surfacelayer.mp4 窗口层级树相关sur

    2024年02月12日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包