赞
踩
android-9.0.0_r8
JNI涉及java层和C/C++层,ANR超时判断在C/C++层
Input事件超时主要是事件分发超时,从标题就有提示。
InputDispatcherThread是InputDispatcher的notifyMotion函数唤醒,执行InputDispatcherThread的threadLoop函数
dispatchOnceInnerLocked开始计时,handleTargetsNotReadyLocked里进行判断超时。
在派发事件时,dispatchKeyLocked()和dispatchMotionLocked(), 需要找到当前的焦点窗口,焦点窗口才是最终接收事件的地方,找窗口的过程就会判断是否已经发生了ANR。
1、当前时间,ANR计时的起点
2、当分发被冻结,则不再处理超时和分发事件的工作
3、如果isAppSwitchDue为true,说明没有及时响应HOME键等操作,则抢占分发,丢弃其他所有即将要处理的事件。
4、mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量;并重置ANR时间
5、根据EventEntry的type类型分别处理,比如按键调用dispatchKeyLocked分发事件
6、执行完成(done)的处理。根据dropReason(默认DROP_REASON_NOT_DROPPED不处理)来决定是否丢失事件;releasePendingEventLocked 释放当前正在处理的事件(即mPendingEvent); 强制立刻执行轮询LONG_LONG_MIN
ANR输出相关原因
int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry, const sp<InputApplicationHandle>& applicationHandle, const sp<InputWindowHandle>& windowHandle, nsecs_t* nextWakeupTime, const char* reason) { if (applicationHandle == NULL && windowHandle == NULL) { if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) { #if DEBUG_FOCUS ALOGD("Waiting for system to become ready for input. Reason: %s", reason); #endif mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY; mInputTargetWaitStartTime = currentTime; mInputTargetWaitTimeoutTime = LONG_LONG_MAX; mInputTargetWaitTimeoutExpired = false; mInputTargetWaitApplicationHandle.clear(); } } else { if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) { #if DEBUG_FOCUS ALOGD("Waiting for application to become ready for input: %s. Reason: %s", getApplicationWindowLabelLocked(applicationHandle, windowHandle).c_str(), reason); #endif nsecs_t timeout; if (windowHandle != NULL) { timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT); } else if (applicationHandle != NULL) { timeout = applicationHandle->getDispatchingTimeout( DEFAULT_INPUT_DISPATCHING_TIMEOUT); } else { timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT; } mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY; mInputTargetWaitStartTime = currentTime; mInputTargetWaitTimeoutTime = currentTime + timeout; mInputTargetWaitTimeoutExpired = false; mInputTargetWaitApplicationHandle.clear(); if (windowHandle != NULL) { mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle; } if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) { mInputTargetWaitApplicationHandle = applicationHandle; } } } if (mInputTargetWaitTimeoutExpired) { return INPUT_EVENT_INJECTION_TIMED_OUT; } if (currentTime >= mInputTargetWaitTimeoutTime) { onANRLocked(currentTime, applicationHandle, windowHandle, entry->eventTime, mInputTargetWaitStartTime, reason); // Force poll loop to wake up immediately on next iteration once we get the // ANR response back from the policy. *nextWakeupTime = LONG_LONG_MIN; return INPUT_EVENT_INJECTION_PENDING; } else { // Force poll loop to wake up when timeout is due. if (mInputTargetWaitTimeoutTime < *nextWakeupTime) { *nextWakeupTime = mInputTargetWaitTimeoutTime; } return INPUT_EVENT_INJECTION_PENDING; } }
currentTime >= mInputTargetWaitTimeoutTime超时判断,执行onANRLocked
1、currentTime是指执行dispatchOnceInnerLocked方法体的起点
2、mInputTargetWaitTimeoutTime = currentTime + timeout默认超时时间是五秒DEFAULT_INPUT_DISPATCHING_TIMEOUT
3、mInputTargetWaitCause等于INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY(应用没有准备就绪),而前面resetANRTimeoutsLocked()过程是唯一用于重置等待理由的地方。可见,ANR时间区间是从dispatchOnceInnerLocked方法体的起点,直到下次执行handleTargetsNotReadyLocked()方法的这段应用未准备就绪的时间段,该时间段是否超过5s来决定是否触发ANR。
JNI层
java层
和ANR service TimeOut 超时判断、ANR Broadcast TimeOut 超时判断一样使用AppErrors.appNotResponding最终输出Log
ANR机制以及问题分析
Input系统—ANR原理分析
Input系统—InputDispatcher线程
Android输入系统(三)InputReader的加工类型和InputDispatcher的分发过程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。