ANR 根本原因:InputDispatcher 超时机制
java
// frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
void updateInputWindowsLw(boolean force) {
// 关键流程:构建可接收输入的窗口列表
for (WindowState w : mService.mWindowManager.getWindowListLocked()) {
if (w.canReceiveKeys()) { // FLAG_NOT_FOCUSABLE 窗口被排除
addInputWindowHandleLw(handles, w);
}
}
// 将窗口列表同步到 InputDispatcher
mService.mInputManager.setInputWindows(handles);
}
事件分发核心流程

关键源码路径分析
1. 窗口焦点状态更新 (WindowManagerService
)
java
// frameworks/base/services/core/java/com/android/server/wm/WindowState.java
boolean canReceiveKeys() {
return (mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0; // 关键判断
}
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
void setFocusedWindow(WindowState newFocus) {
if (newFocus == null || !newFocus.canReceiveKeys()) {
mInputMonitor.setFocusedAppLw(null); // 清除焦点应用
}
}
2. InputDispatcher 焦点处理 (Native 层
)
cpp
// frameworks/native/services/inputflinger/InputDispatcher.cpp
bool InputDispatcher::findFocusedWindowTargetsLocked(...) {
if (mFocusedWindowHandle == nullptr) {
// ANR 触发点:记录超时原因
reason = StringPrintf("because there is no focused window");
return false;
}
// ...正常分发流程...
}
3. ANR 检测机制
cpp
// frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::processAnrsLocked() {
if (currentTime > mAnrTracker.firstTimeout()) {
// 生成 ANR 报告
dispatchUnresponsive = createAnrMessageLocked();
// 回调到 Java 层
mPolicy->notifyUnresponsive(dispatchUnresponsive);
}
}
多模块协同故障链

解决方案:避免 ANR 的架构设计
方案 1:动态焦点控制 + 心跳机制
java
// 在 Activity 中实现焦点状态机
private val focusStateMachine = object : FocusStateListener {
override fun onNeedFocus() {
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window.decorView.post {
window.decorView.requestFocus()
}
}
override fun onCanReleaseFocus() {
window.setFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
)
}
}
// 添加输入事件心跳检测
class InputHeartbeatTracker(context: Context) {
fun start() {
Handler(Looper.getMainLooper()).postDelayed(heartbeatRunnable, 1000)
}
private val heartbeatRunnable = object : Runnable {
override fun run() {
if (SystemClock.uptimeMillis() - lastEventTime > 3000) {
focusStateMachine.onNeedFocus() // 防止长期无焦点
}
handler.postDelayed(this, 1000)
}
}
}
方案 2:自定义 InputChannel 代理
java
// 创建透明输入代理窗口
fun createInputProxyWindow() {
val params = WindowManager.LayoutParams(
TYPE_APPLICATION_OVERLAY,
FLAG_NOT_FOCUSABLE or FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSPARENT
).apply {
inputFeatures = INPUT_FEATURE_PROXY_INPUT
}
val proxyView = View(context).apply {
setOnKeyListener { _, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_BACK) {
handleBackPressed()
true
} else false
}
}
windowManager.addView(proxyView, params)
}
方案 3:WMS 层 Hook (需系统权限)
java
// 通过 AIDL 定制 WindowManagerPolicy
interface ICustomWindowPolicy : IInterface {
fun shouldSkipFocusCheck(attrs: WindowManager.LayoutParams): Boolean
}
// 在 PhoneWindowManager 中注入
override fun interceptKeyBeforeQueueing(event: KeyEvent, policyFlags: Int): Int {
if (customPolicy.shouldSkipFocusCheck(topWindow.attrs)) {
return ACTION_PASS_TO_USER // 绕过焦点检查
}
return super.interceptKeyBeforeQueueing(event, policyFlags)
}
性能优化表:焦点控制策略对比
策略 | ANR 风险 | 系统负担 | 兼容性 | 实现复杂度 |
---|---|---|---|---|
动态焦点控制 | ★☆☆☆☆ | 中 | API 1+ | ★★☆☆☆ |
InputChannel 代理 | ★★☆☆☆ | 高 | API 26+ | ★★★★☆ |
WMS 层 Hook | ☆☆☆☆☆ | 低 | 需ROOT | ★★★★★ |
透明Activity桥接 | ★★★☆☆ | 中 | API 1+ | ★★★☆☆ |
核心设计原则 :在 Android 输入子系统中,
FLAG_NOT_FOCUSABLE
会破坏 WMS(WindowManagerService) 和 InputDispatcher 之间的焦点契约。任何长期处于无焦点窗口的状态都会触发系统的安全保护机制(ANR),必须通过焦点状态心跳 或输入通道代理维持事件流的连续性。