应用ANR:NoFocudWindow流程分析

更新时间:2023-05-06 03:12:11 阅读: 评论:0

// ......
// mPendingEvent默认为空,会从mInboundQueue中获取到值
if (!mPendingEvent) {
// mInboundQueue是通过enqueueInboundEventLocked()赋值,所以有事件的时候mInboundQueue不为空        // notifyConfigurationChanged() -> enqueueInboundEventLocked()
// notifyKey() -> enqueueInboundEventLocked()
// notifyMotion() -> enqueueInboundEventLocked()
// notifyDeviceRet() -> enqueueInboundEventLocked()
// injectInputEvent() -> enqueueInboundEventLocked()
// tInputWindowsLocked() -> enqueueFocusEventLocked()
if (pty()) {
// ......
// 如果mInboundQueue也没有pending的事件,直接返回
if (!mPendingEvent) {
return;
}
} el {
// ⼀般⾛这个流程,取mInboundQueue第⼀个元素
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
traceInboundQueueLengthLocked();
}
// ......
}
// ⾛到这个地⽅,mPendingEvent⼀般不会为空
ALOG_ASSERT(mPendingEvent != nullptr);
bool done = fal;
DropReason dropReason = DropReason::NOT_DROPPED;
// ......
// 根据pendingEvent的类型创建不同的实例去分发事件
// 不同的⼊⼝的类型不⼀样,如调⽤了notifyKey()就会创建⼀个KeyEntry
switch (mPendingEvent->type) {
// 来源:notifyConfigurationChanged() -> new ConfigurationChangedEntry()
ca EventEntry::Type::CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
static_cast<ConfigurationChangedEntry*>(mPendingEvent);
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DropReason::NOT_DROPPED; // configuration changes are never dropped
break;
}
// 来源:notifyDeviceRet() -> new DeviceRetEntry()
ca EventEntry::Type::DEVICE_RESET: {
DeviceRetEntry* typedEntry = static_cast<DeviceRetEntry*>(mPendingEvent);
done = dispatchDeviceRetLocked(currentTime, typedEntry);
dropReason = DropReason::NOT_DROPPED; // device rets are never dropped
break;
}
// 来源:tInputWindowsLocked() -> enqueueFocusEventLocked() -> new FocusEntry()
ca EventEntry::Type::FOCUS: {
FocusEntry* typedEntry = static_cast<FocusEntry*>(mPendingEvent);
dispatchFocusLocked(currentTime, typedEntry);
done = true;
dropReason = DropReason::NOT_DROPPED; // focus events are never dropped
break;
}
// 来源:notifyKey() -> new KeyEntry()
ca EventEntry::Type::KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
// ......
// 跳转到findFocudWindowTargetsLocked() -> dispatchEventLocked()
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
// 来源:notifyMotion() -> new MotionEntry()
ca EventEntry::Type::MOTION: {
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
// ......
/
/ 跳转到findFocudWindowTargetsLocked() -> dispatchEventLocked()
done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
}
前⾯看到,是否触发ANR跟focudWindowHandle和focudApplicationHandle有关,那么这两个值的赋值流程是在哪⾥呢?
跟踪代码流程,可以看到,这两个流程都是WindowManagerService在窗⼝切换的过程中,设置到InputDispatcher中的,最后调
⽤tInputWindowsLocked()设置focudWindowHandle,调⽤tFocudApplication()设置focudApplicationHandle,相关流程如下,关键步骤有注释。
tInputWindow.PNG
// frameworks/native/rvices/inputflinger/dispatcher/InputDispatcher.cpp
// 当VSYNC信号来了之后,会调⽤到SurfaceFlinger的onMessageInvalidate()⽅法
// SurfaceFlinger::onMessageInvalidate()
//  ==> SurfaceFlinger: updateInputFlinger()
//    ==> SurfaceFlinger: updateInputWindowInfo()
//      ==> InputManager::tInputWindows()
//        ==> InputDispatcher::tInputWindows()
//          ==> InputDispatcher::tInputWindowsLocked()
void InputDispatcher::tInputWindowsLocked(
const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
/
/ ......
const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
// 更新mWindowHandlesByDisplay这个map,然后通过getWindowHandlesLocked()找newFocudWindowHandle
updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId);
sp<InputWindowHandle> newFocudWindowHandle = nullptr;
bool foundHoveredWindow = fal;
// 在mWindowHandlesByDisplay这个map⾥⾯找newFocudWindowHandle
for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
// newFocudWindowHandle要不为空,windowHandle具备focusable和visible属性
if (!newFocudWindowHandle && windowHandle->getInfo()->hasFocus &&
windowHandle->getInfo()->visible) {
// 给newFocudWindowHandle赋值,最后这个值存到mFocudWindowHandlesByDisplay这个map
newFocudWindowHandle = windowHandle;
}
if (windowHandle == mLastHoverWindowHandle) {
foundHoveredWindow = true;
}
}
if (!foundHoveredWindow) {
mLastHoverWindowHandle = nullptr;
}
/
/ 在mFocudWindowHandlesByDisplay这个map⾥找当前的焦点窗⼝
sp<InputWindowHandle> oldFocudWindowHandle =
getValueByKey(mFocudWindowHandlesByDisplay, displayId);
// 判断oldFocudWindowHandle是否等于newFocudWindowHandle,如果相等则不⾛focus change流程
if (!haveSameToken(oldFocudWindowHandle, newFocudWindowHandle)) {
// 如果当前的焦点窗⼝不为空,需要从mFocudWindowHandlesByDisplay移除掉
if (oldFocudWindowHandle != nullptr) {
为空

本文发布于:2023-05-06 03:12:11,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/536873.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:流程   事件   实例   看到   是否
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图