Android InputEventReceiver事件接收流程分析

这篇具有很好参考价值的文章主要介绍了Android InputEventReceiver事件接收流程分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文基于Android 12。

InputEvent经过inputflinger读取后,通过Inputchannel发送到Java层的InputEventReceiver对象,输入事件和View的状态强相关,事件发送需要确定当前的焦点App,焦点Window(View),事件接收者是谁,所以InputEventReceiver对象也在View的创建流程中被初始化,ViewRootImpl中通过InputChannel参数实例化WindowInputEventReceiver,其覆盖了父类InputEventReceiver的onInputEvent()方法。

一、WindowInputEventReceiver

    // ViewRootImpl.java    
    	final class WindowInputEventReceiver extends InputEventReceiver {
            public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
                super(inputChannel, looper);
            }
          
            @Override
            public void onInputEvent(InputEvent event) {
                    enqueueInputEvent(event, this, 0, true);
            }
        }

调用enqueueInputEvent方法。

    // ViewRootImpl.java 
        QueuedInputEvent mPendingInputEventHead;
    
        void enqueueInputEvent(InputEvent event,
                InputEventReceiver receiver, int flags, boolean processImmediately) {
            QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
            QueuedInputEvent last = mPendingInputEventTail;
            if (last == null) {
                mPendingInputEventHead = q;
                mPendingInputEventTail = q;
            } else {
                last.mNext = q;
                mPendingInputEventTail = q;
            }
            mPendingInputEventCount += 1;
            doProcessInputEvents();
        }

enqueueInputEvent对事件通过mPendingInputEventHead变量维护一个事件队列,doProcessInputEvents()进行下一步处理。

    // ViewRootImpl.java 
    	void doProcessInputEvents() {
            while (mPendingInputEventHead != null) {
                QueuedInputEvent q = mPendingInputEventHead;
                mPendingInputEventHead = q.mNext;
                if (mPendingInputEventHead == null) {
                    mPendingInputEventTail = null;
                }
                q.mNext = null;
              	deliverInputEvent(q);
            }
        }

doProcessInputEvents对mPendingInputEventHead队列中所有事件进行分发。

    // ViewRootImpl.java     
    	private void deliverInputEvent(QueuedInputEvent q) {
            try {
              	InputStage stage;
                if (q.shouldSendToSynthesizer()) {
                    stage = mSyntheticInputStage;
                } else {
                    stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
                }
                if (stage != null) {
                    handleWindowFocusChanged();
                    stage.deliver(q);
                } else {
                    finishInputEvent(q);
                }
            }
        }

将事件交给InputStage处理,InputStage是Android实现事件责任链的基类,deliver()方法中处理是否传递给下一个阶段:forward(),或者结束事件的传递:finish()。

二、InputState

    // ViewRootImpl.java 
    abstract class InputStage {        
        public final void deliver(QueuedInputEvent q) {
            if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
                forward(q);
            } else if (shouldDropInputEvent(q)) {
                finish(q, false);
            } else {
                traceEvent(q, Trace.TRACE_TAG_VIEW);
                final int result;
                try {
                    result = onProcess(q);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                }
                apply(q, result);
            }
        }
    }

InputStage是一个抽象类,deliver方法中调用了onProcess(q),子类覆盖onProcess方法实现自己的操作逻辑。

在ViewRootImpl的setView方法中定义了InputState的责任链:

    // ViewRootImpl.java 
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
            // Set up the input pipeline.
            CharSequence counterSuffix = attrs.getTitle();
            mSyntheticInputStage = new SyntheticInputStage();
            InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
            InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
                    "aq:native-post-ime:" + counterSuffix);
            InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
            InputStage imeStage = new ImeInputStage(earlyPostImeStage,
                    "aq:ime:" + counterSuffix);
            InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
            InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
                    "aq:native-pre-ime:" + counterSuffix);
            mFirstInputStage = nativePreImeStage;
            mFirstPostImeInputStage = earlyPostImeStage;
    }

从实例化的顺序可知事件传递阶段的流程:

nativePreImeStage->viewPreImeStage->imeStage->earlyPostImeStage->nativePostImeStage->viewPostImeStage->mSyntheticInputStage

关于各个InputStage的官方说明:

InputState Description
NativePreImeInputStage Delivers pre-ime input events to a native activity. Does not support pointer events.
ViewPreImeInputStage Delivers pre-ime input events to the view hierarchy. Does not support pointer events.
ImeInputStage Delivers input events to the ime. Does not support pointer events.
EarlyPostImeInputStage Performs early processing of post-ime input events.
NativePostImeInputStage Delivers post-ime input events to a native activity.
ViewPostImeInputStage Delivers post-ime input events to the view hierarchy.
SyntheticInputStage Performs synthesis of new input events from unhandled input events.

可参考文章:https://blog.csdn.net/vviccc/article/details/93377708

一般用户接触到最多的Activity和View属于ViewPostImeInputStage阶段。

三、ViewPostImeInputStage

    // ViewRootImpl.java 
    	final class ViewPostImeInputStage extends InputStage {
            @Override
            protected int onProcess(QueuedInputEvent q) {
                if (q.mEvent instanceof KeyEvent) {
                    return processKeyEvent(q);
                } else {
                    final int source = q.mEvent.getSource();
                    if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                        return processPointerEvent(q);
                    } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                        return processTrackballEvent(q);
                    } else {
                        return processGenericMotionEvent(q);
                    }
                }
            }
        }

processKeyEvent处理KeyEvent,MotionEvent有两种情况,触屏操作的MotionEvent调用processPointerEvent处理,轨迹球操作的MotionEvent调用processTrackballEvent处理。

接着查看processPointerEvent方法:

    // ViewRootImpl.java 
    private int processPointerEvent(QueuedInputEvent q) {
        final MotionEvent event = (MotionEvent)q.mEvent;
        boolean handled = mView.dispatchPointerEvent(event);
        maybeUpdatePointerIcon(event);
        maybeUpdateTooltip(event);
        return handled ? FINISH_HANDLED : FORWARD;
    }

调用mView.dispatchPointerEvent(event)方法。

    // View.java    
    	@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        public final boolean dispatchPointerEvent(MotionEvent event) {
            if (event.isTouchEvent()) {
                return dispatchTouchEvent(event);
            } else {
                return dispatchGenericMotionEvent(event);
            }
        }

终于到了熟悉的dispatchTouchEvent(event)方法。接下来就是熟悉onInterceptTouchEvent(),onTouchEvent()。文章来源地址https://www.toymoban.com/news/detail-433237.html

到了这里,关于Android InputEventReceiver事件接收流程分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Android系统启动流程分析

           当按下Android系统的开机电源按键时候,硬件会触发引导芯片,执行预定义的代码,然后加载引导程序(BootLoader)到RAM,Bootloader是Android系统起来前第一个程序,主要用来拉起Android系统程序,Android系统被拉起首先肯定会启动Linux内核。 备注: 我们再刷机时候,经常看到

    2024年02月15日
    浏览(47)
  • Android分屏流程分析

    本文基于Android 11。 SystemUI模块中的Divider管理着所有关于分屏的对象: DividerView(分屏分割线,分屏显示界面) SplitScreenTaskOrganizer(分屏Task组织者,分屏逻辑) 这里重点关注分屏逻辑实现SplitScreenTaskOrganizer。 Devider类实现了DisplayController.OnDisplaysChangedListener,系统启动后回调

    2024年02月10日
    浏览(44)
  • Android SystemServer 启动流程分析

    和你一起终身学 习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一、SystemServer 启动的服务有哪些 二、SystemServer启动总体流程概述 三、SystemServer 如何启动,是谁启动的? 四、 SystemServer 启动入门 main 方法 五、SystemServer Run 方法初始与启动 六、

    2024年02月13日
    浏览(47)
  • Android Audio音量设置原理流程分析

    本篇文章主要介绍Android音量设置从App应用层到framework层执行流程,以及相关的细节和原理分析,建议在阅读此文章前去看博主的混音理论篇的声音的音量属性和声音相关公式的推导章节,这对阅读时理解音量等级、音量分贝计算有着很大的益处;如果阅读时发现文章有错误,

    2024年02月15日
    浏览(53)
  • Android10.0 人脸解锁流程分析

    人脸解锁概述 人脸解锁即用户通过注视设备的正面方便地解锁手机或平板。Android 10 为支持人脸解锁的设备在人脸认证期间添加了一个新的可以安全处理相机帧、保持隐私与安全的人脸认证栈的支持,也为安全合规地启用集成交易的应用(网上银行或其他服务)提供了一种容

    2024年02月03日
    浏览(46)
  • android framework之Applicataion启动流程分析

    Application启动流程框架分析 启动方式一:通过Launcher启动app 启动方式二:在某一个app里启动第二个app的Activity. 以上两种方式均可触发app进程的启动。但无论哪种方式,最终通过通过调用AMS的startActivity()来启动application的。    根据上图分析, 要启动一个Application,需要涉及五

    2024年02月11日
    浏览(46)
  • 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)
  • 【Android12】Monkey压力测试源码执行流程分析

    Monkey是Android提供的用于应用程序自动化测试、压力测试的测试工具。 其源码路径(Android12)位于 部署形式为Java Binary 通过Monkey,可以模拟用户的Touch(单指、多指、手势)、按键(key)事件等,检测应用程序发生的ANR、Crash事件,并收集相关Debug信息等。 例如测试应用com.packa

    2024年03月22日
    浏览(43)
  • Android9.0 系统Framework发送通知流程分析

      在android 9.0的系统rom定制化开发中,在systemui中一个重要的内容就是系统通知的展示,在状态栏展示系统发送通知的图标,而在 系统下拉通知栏中展示接收到的系统发送过来的通知,所以说对系统framework中发送通知的流程分析很重要,接下来就来分析下系统 通知从framework到

    2024年02月02日
    浏览(44)
  • Android 13 网络 Adb相关流程深入分析研究

    通过代码分析发现Android13 上对 网络adb 进行了限制! Android13原生代码要求:必现连接上某个wifi,才能进行adb ,并且切换wifi或者关闭wifi都是会停止adb。 并且Android13 上 wifi adb 端口号每次是变化的,这个也是很不方便的! 如果要做成Android11 或者之前一样,设备连接WiFi/有线网

    2024年02月09日
    浏览(54)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包