android anr的分析以及input事件的流程分析

native的 InputDispatcher 每发送一个事件给应用就将这个事件和它的超时时间放入waitQueue 中,然后如果应用及时响应这个事件或者说这个事件及时得到了确认 ,那我们就从waitQueue 中把这个事件删除。
然后我们就可以检测waitQueue中的元素:如果某个元素的超时时间大于现在的时间,那肯定是超时,无响应了 。
如下:

 /**
 * Connection is responsive if it has no events in the waitQueue that are older than the
 * current time.
 */
bool isConnectionResponsive(const Connection& connection) {
    const nsecs_t currentTime = now();
    for (const DispatchEntry* entry : connection.waitQueue) {
        if (entry->timeoutTime < currentTime) {
            return false;
        }
    }
    return true;
}

每一个事件都有一个 seq ,

InputPublisher::receiveConsumerResponse

会收到一个事件,这个事件的type是FINISHED :
msg.header.type == InputMessage::Type::FINISHED
那是在什么地方把这个type设置为FINISHED的呢?

frameworks/base/core/java/android/view/InputEventReceiver.java 的 finishInputEvent 会调用 jni的
nativeFinishInputEvent,

frameworks/base/core/java/android/view/ViewRootImpl.java 的 WindowInputEventReceiver 的 onInputEvent 方法会调用上面的 finishInputEvent 方法 ,

那 onInputEvent 是什么地方调用的? : 是在这个类的 dispatchInputEvent 方法中 。
而 dispatchInputEvent 是被 jni 的 NativeInputEventReceiver::consumeEvents 调用 ,

而 NativeInputEventReceiver::consumeEvents 被 NativeInputEventReceiver::handleEvent 调用,
而 NativeInputEventReceiver::handleEvent 是当 inputchannel 有新的事件时被 looper 调用 ,所以总结下 调用流程为 :

inputchannel 有新的事件到达
NativeInputEventReceiver::handleEvent
NativeInputEventReceiver::consumeEvents
frameworks/base/core/java/android/view/ViewRootImpl.java.WindowInputEventReceiver的 dispatchInputEvent()
frameworks/base/core/java/android/view/ViewRootImpl.java.WindowInputEventReceiver的 onInputEvent()

当然我们可以通过添加log打印来验证上面的结论。

frameworks/native/services/inputflinger/dispatcher/Connection.h

Connection.waitQueue : 已经发送给应用,而还没有收到应用的确认信息。

事件的处理流程:
以下截图有助于我们对事件流程的分析.

在这里插入图片描述

Activity 创建的时候在其 attach 方法中会创建一个PhoneWindow , 而 PhoneWindow 在其内部通过 installDecor 方法来创建一个 DecorView;
Activity 持有对 DecorView的引用,叫 mDecor。

Activity 在其makeVisible方法中将 mDecor 添加至 WindowManager:

  void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

而 Activity的getWindowManager() 的实际对象是 WindowManagerImpl : PhoneWindow. getWindowManager();

所以 makeVisible 方法中实际调用的是 WindowManagerImpl 的 addView 方法 。

而 WindowManagerImpl 的 addView 方法又调用了 WindowManagerGlobal 的addView方法 。

WindowManagerGlobal的 addView 会创建一个 ViewRootImpl ,然后将参数中的view设置到 ViewRootImpl 中, 也就是 将 ViewRootImpl 的变量 mView 为DecorView 。这样 DecorView 就可以收到各种事件了。
比如在其 processPointerEvent 中调用 mView.dispatchPointerEvent(event)方法中将事件发送给 mView 来处理 。

ViewRootImpl 是 在什么地方被创建的?
ViewRootImpl 的 mView 是谁?

后期会继续完善。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值