Android16 Input 事件分发链路
·
覆盖范围:硬件中断 → EventHub → InputReader → InputDispatcher → Socket → ViewRootImpl → View 树
一、整体架构分层
┌──────────────────────────────────────────────────────────┐
│ 硬件层 │
│ 触摸屏产生中断 → 内核 input 子系统 │
│ 写入 /dev/input/eventX │
└───────────────────────────┬──────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────┐
│ Native 层 │
│ │
│ ┌─────────┐ ┌─────────────┐ ┌──────────────────┐ │
│ │EventHub │──▶│ InputReader │──▶│ InputDispatcher │ │
│ │读硬件事件│ │ 加工事件 │ │ 找窗口 发Socket │ │
│ └─────────┘ └─────────────┘ └──────────────────┘ │
└───────────────────────────┬──────────────────────────────┘
↓ Unix Domain Socket
┌──────────────────────────────────────────────────────────┐
│ 应用进程层 │
│ │
│ InputEventReceiver → ViewRootImpl → InputStage 责任链 │
│ DecorView → Activity → ViewGroup → View │
└──────────────────────────────────────────────────────────┘
二、第一层:EventHub 读取硬件事件
文件:frameworks/native/services/inputflinger/reader/EventHub.cpp
input_event 结构体(Linux 内核定义)
struct input_event {
struct timeval time; // 时间戳
__u16 type; // EV_ABS(触摸)/ EV_KEY(按键)/ EV_SYN(同步)
__u16 code; // ABS_MT_POSITION_X/Y / KEY_POWER 等
__s32 value; // 坐标值或按键状态(1=按下 0=抬起)
};
getEvents() 核心流程
std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
std::scoped_lock _l(mLock); // 加锁
for (;;) {
// ① 处理待关闭设备,生成 DEVICE_REMOVED 事件
for (auto it = mClosingDevices.begin(); ...) {
events.push_back({ .when=now, .deviceId=id, .type=DEVICE_REMOVED });
}
// ② 扫描新设备(/dev/input/ 目录)
if (mNeedToScanDevices) {
scanDevicesLocked(); // 打开新设备 fd,注册到 epoll
}
// ③ 上报新打开的设备,生成 DEVICE_ADDED 事件
while (!mOpeningDevices.empty()) {
events.push_back({ .when=now, .deviceId=id, .type=DEVICE_ADDED });
mDevices.insert_or_assign(device->id, std::move(device));
}
// ④ 遍历 epoll 就绪的 fd,读取真实输入事件
while (mPendingEventIndex < mPendingEventCount) {
const epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
if (eventItem.data.fd == mINotifyFd) {
mPendingINotify = true; // 设备插拔通知,延迟处理
continue;
}
if (eventItem.data.fd == mWakeReadPipeFd) {
awoken = true; // 被主动唤醒(配置变化等)
continue;
}
// 读取输入设备数据
int32_t readSize = read(device->fd, readBuffer.data(), bufferBytes);
const size_t count = readSize / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
events.push_back({
.when = processEventTimestamp(iev), // 时间戳校正
.readTime = systemTime(SYSTEM_TIME_MONOTONIC),
.deviceId = deviceId,
.type = iev.type, // EV_ABS / EV_KEY
.code = iev.code, // ABS_MT_POSITION_X 等
.value = iev.value, // 坐标值
});
}
}
// ⑤ 有事件就返回,没有就 epoll_wait 阻塞等待
if (!events.empty() || awoken) break;
mLock.unlock();
int pollResult = epoll_wait(mEpollFd, mPendingEventItems,
EPOLL_MAX_EVENTS, timeoutMillis);
mLock.lock();
if (pollResult == 0) break; // 超时
mPendingEventCount = size_t(pollResult);
}
return events;
}
EventHub 关键设计
| 机制 | 作用 |
|---|---|
epoll_wait |
阻塞等待,有事件才唤醒,不空转 |
inotify |
监听 /dev/input/ 目录变化,检测设备插拔 |
mWakeReadPipeFd |
特殊管道,配置变化时主动唤醒 epoll |
EPOLLWAKEUP |
持有 wake lock 直到下次 epoll_wait,防止休眠丢事件 |
| buffer 满回退 | mPendingEventIndex -= 1,下次从当前设备继续读,不丢事件 |
三、第二层:InputReader 加工事件
文件:frameworks/native/services/inputflinger/reader/InputReader.cpp
loopOnce() 主循环
void InputReader::loopOnce() {
// ① 加锁,计算超时时间
{
std::scoped_lock _l(mLock);
oldGeneration = mGeneration;
timeoutMillis = -1; // 默认无限等待
auto changes = mConfigurationChangesToRefresh;
if (changes.any()) {
timeoutMillis = 0; // 有配置变化,立即处理
refreshConfigurationLocked(changes); // 刷新灵敏度/键映射等配置
} else if (mNextTimeout != LLONG_MAX) {
// 有定时任务(长按检测等),计算剩余等待时间
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // 解锁,避免阻塞期间其他线程无法访问
// ② 阻塞读取原始事件(无锁)
std::vector<RawEvent> events = mEventHub->getEvents(timeoutMillis);
// ③ 加锁,处理事件
{
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all(); // 心跳
if (!events.empty()) {
mPendingArgs += processEventsLocked(events.data(), events.size());
}
// 处理定时超时(如长按触发)
if (mNextTimeout != LLONG_MAX && now >= mNextTimeout) {
mNextTimeout = LLONG_MAX;
mPendingArgs += timeoutExpiredLocked(now);
}
// 设备列表有变化,通知上层
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
inputDevices = getInputDevicesLocked();
}
std::swap(notifyArgs, mPendingArgs);
} // 解锁
// ④ 锁外通知 InputDispatcher(防止死锁)
for (const NotifyArgs& args : notifyArgs) {
mNextListener.notify(args);
}
}
processEventsLocked() 批量处理
std::list<NotifyArgs> InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
// 真实硬件事件:把同一设备的连续事件打包批量处理
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) break;
batchSize++;
}
// 交给对应设备的 InputMapper 处理
out += processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
// 合成事件:设备增删
switch (rawEvent->type) {
case DEVICE_ADDED: addDeviceLocked(...); break;
case DEVICE_REMOVED: removeDeviceLocked(...); break;
case FINISHED_DEVICE_SCAN: handleConfigurationChangedLocked(...); break;
}
}
count -= batchSize;
rawEvent += batchSize; // 指针后移
}
return out;
}
InputMapper:核心加工逻辑
原始 RawEvent(只有 type/code/value)
↓
TouchInputMapper(触摸屏专属)
- 多点触摸协议解析(A 协议:绝对坐标 / B 协议:Slot 追踪)
- 坐标归一化(原始值 → 屏幕像素坐标)
- 屏幕方向变换(横竖屏旋转校正)
- 手势预识别(区分 TAP / LONG_PRESS / SCROLL)
↓
NotifyMotionArgs(包含完整触摸信息)
- action(DOWN/MOVE/UP)
- pointerCount(手指数量)
- pointerCoords[](每个手指的 x/y/pressure/size)
- eventTime / deviceId / source / displayId
notify() 的类型分发
// InputListenerInterface::notify() 是非虚函数,基类写死
void InputListenerInterface::notify(const NotifyArgs& generalArgs) {
Visitor v{
[&](const NotifyMotionArgs& args) { notifyMotion(args); },
[&](const NotifyKeyArgs& args) { notifyKey(args); },
[&](const NotifyInputDevicesChangedArgs& args) { notifyInputDevicesChanged(args); },
// ... 其他类型
};
std::visit(v, generalArgs);
// std::visit = 识别 variant 的实际类型,调用对应 lambda
// 等价于 Java 的 instanceof 判断
}
// notifyMotion/notifyKey 是虚函数 → 实际调用 InputDispatcher 的实现
// mNextListener 的真实类型(InputManager.cpp):
// mDispatcher = createInputDispatcher(mPolicy);
// mReader = new InputReader(mEventHub, mPolicy, *mDispatcher);
// ↑ 直接传入 InputDispatcher
// 继承链:InputDispatcher : InputDispatcherInterface : InputListenerInterface
为什么锁外 notify?
InputReader 和 InputDispatcher 互相可能回调对方的方法:
Dispatcher 处理事件时可能查询 InputReader 的 getScanCodeState()
如果持锁调用 notify,Dispatcher 回调时需要再次加锁 → 死锁
设计原则:
加锁:处理事件、修改内部状态
解锁:阻塞等待、跨组件通知
四、第三层:InputDispatcher 路由与分发
文件:frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
4.1 notifyMotion():校验 + 入队
void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
// ① 合法性校验
Result<void> motionCheck = validateMotionEvent(
args.action, args.actionButton,
args.getPointerCount(), args.pointerProperties.data());
if (!motionCheck.ok()) { return; } // 非法事件丢弃
// ② 标记可信(来自硬件,非注入伪造)
policyFlags |= POLICY_FLAG_TRUSTED;
// ③ Policy 入队前拦截(锁外,因为可能做 Binder 调用)
mPolicy.interceptMotionBeforeQueueing(args.displayId, args.eventTime, policyFlags);
// 屏幕熄灭时:移除 POLICY_FLAG_PASS_TO_USER,事件只用于亮屏
{ // 加锁
// ④ 处理进行中的手势(即使 Policy 拒绝,手势中的事件也要继续)
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
if (touchState.hasTouchingPointers(args.deviceId)) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
// ⑤ InputFilter 过滤(无障碍服务)
if (shouldSendMotionToInputFilterLocked(args)) {
mLock.unlock();
if (!mPolicy.filterInputEvent(event, policyFlags)) return; // 被消费
mLock.lock();
}
// ⑥ 构造 MotionEntry 入队
auto newEntry = std::make_unique<MotionEntry>(
args.id, args.eventTime, args.deviceId, args.source,
args.displayId, policyFlags, args.action, ...);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // 解锁
if (needWake) mLooper->wake(); // 唤醒 Dispatcher 线程
}
4.2 enqueueInboundEventLocked():队列管理
bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry) {
bool needWake = mInboundQueue.empty(); // 队列空才需要唤醒
mInboundQueue.push_back(std::move(newEntry));
// MOVE 事件堆积优化:直接跳到最新,避免触摸响应滞后(跳帧)
if (shouldPruneInboundQueueLocked(motionEntry)) {
mNextUnblockedEvent = mInboundQueue.back();
needWake = true;
}
// AppSwitch 优化:HOME/ENDCALL 设置超时,超时后丢弃其他事件
if (isAppSwitchKeyEvent(keyEntry)) {
mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
}
return needWake;
}
4.3 dispatchOnce():Dispatcher 线程主循环
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LLONG_MAX;
{
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all(); // 心跳
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime); // 处理事件
}
if (runCommandsLockedInterruptable()) {
nextWakeupTime = LLONG_MIN; // 有命令,立即再次处理
}
const nsecs_t nextAnrCheck = processAnrsLocked(); // ANR 超时检查
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
}
// 阻塞等待:mLooper->wake() 调用后从这里醒来
mLooper->pollOnce(toMillisecondTimeoutDelay(currentTime, nextWakeupTime));
}
4.4 dispatchOnceInnerLocked():出队与路由
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
// 从队列取出事件
if (!mPendingEvent) {
if (mInboundQueue.empty()) {
// 队列空:检查是否需要生成按键重复事件
if (mKeyRepeatState.lastKeyEntry) {
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
}
if (!mPendingEvent) return;
} else {
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
}
}
// 丢弃判断
DropReason dropReason = DropReason::NOT_DROPPED;
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) dropReason = DropReason::POLICY;
if (!mDispatchEnabled) dropReason = DropReason::DISABLED;
if (isStaleEvent(currentTime, entry)) dropReason = DropReason::STALE;
if (isAppSwitchDue && !isAppSwitchKey) dropReason = DropReason::APP_SWITCH;
// 按类型路由
switch (mPendingEvent->type) {
case EventEntry::Type::MOTION:
done = dispatchMotionLocked(currentTime, motionEntry,
&dropReason, nextWakeupTime);
break;
case EventEntry::Type::KEY:
done = dispatchKeyLocked(currentTime, keyEntry,
&dropReason, nextWakeupTime);
break;
case EventEntry::Type::FOCUS:
dispatchFocusLocked(currentTime, focusEntry);
break;
}
}
4.5 dispatchMotionLocked():找目标窗口
bool InputDispatcher::dispatchMotionLocked(...) {
if (*dropReason != DropReason::NOT_DROPPED) {
setInjectionResult(*entry, ...);
return true; // 需要丢弃,直接返回
}
std::vector<InputTarget> inputTargets;
const bool isPointerEvent = isFromSource(entry->source, AINPUT_SOURCE_CLASS_POINTER);
if (isPointerEvent) {
// 触摸/鼠标事件:找触摸坐标命中的窗口
inputTargets = findTouchedWindowTargetsLocked(
currentTime, *entry,
&conflictingPointerActions, injectionResult);
// 遍历所有窗口 Z 序
// 检查 FLAG_NOT_TOUCHABLE / FLAG_NOT_FOCUSABLE 等标志
// 处理分割屏、画中画等多窗口场景
} else {
// 键盘/轨迹球:找当前焦点窗口
sp<WindowInfoHandle> focusedWindow =
findFocusedWindowTargetLocked(currentTime, *entry,
nextWakeupTime, injectionResult);
if (injectionResult == InputEventInjectionResult::SUCCEEDED) {
addWindowTargetLocked(focusedWindow,
InputTarget::Flags::FOREGROUND |
InputTarget::Flags::DISPATCH_AS_IS,
{}, getDownTime(*entry), inputTargets);
}
}
// 添加全局监听者(无障碍服务、屏幕录制等)
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
4.6 dispatchEventLocked():向目标发送
void InputDispatcher::dispatchEventLocked(...) {
processInteractionsLocked(*eventEntry, inputTargets);
// 触摸不在焦点窗口时,可能需要转移焦点
pokeUserActivityLocked(*eventEntry);
// 通知 PowerManager 有用户活动,防止熄屏
for (const InputTarget& inputTarget : inputTargets) {
std::shared_ptr<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
}
// connection 为 null:窗口已销毁,丢弃
}
}
4.7 startDispatchCycleLocked():ANR 计时 + 发送
void InputDispatcher::startDispatchCycleLocked(...) {
while (connection->status == Connection::Status::NORMAL
&& !connection->outboundQueue.empty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
// ANR 计时开始(默认 5 秒,这是 Input ANR 的起点)
const auto timeout = getDispatchingTimeoutLocked(connection);
dispatchEntry->timeoutTime = currentTime + timeout.count();
status_t status;
switch (eventEntry.type) {
case EventEntry::Type::MOTION:
status = publishMotionEvent(*connection, *dispatchEntry);
break;
case EventEntry::Type::KEY:
status = connection->inputPublisher.publishKeyEvent(...);
break;
}
if (status == WOULD_BLOCK) {
break; // Socket 缓冲区满,等应用消费后继续
}
// 移入 waitQueue,等待应用 finish 回执
// 超时没收到 finish → processAnrsLocked() 触发 ANR
connection->outboundQueue.pop_front();
connection->waitQueue.push_back(dispatchEntry);
}
}
4.8 publishMotionEvent():坐标变换 + Socket 发送
status_t InputDispatcher::publishMotionEvent(Connection& connection,
DispatchEntry& dispatchEntry) const {
// 坐标缩放(处理多屏幕、不同密度)
if (globalScaleFactor != 1.0f) {
for (uint32_t i = 0; i < pointerCount; i++) {
scaledCoords[i].scale(globalScaleFactor, 1, 1);
}
}
// HMAC 签名,防止应用伪造注入事件
std::array<uint8_t, 32> hmac = getSignature(motionEntry, dispatchEntry);
// 通过 InputPublisher 发送(内部调用 InputChannel::sendMessage)
return connection.inputPublisher.publishMotionEvent(
dispatchEntry.seq, // 序列号,finish 回执配对用
dispatchEntry.resolvedAction,
dispatchEntry.transform, // 窗口坐标变换矩阵
motionEntry.pointerCount,
motionEntry.pointerProperties,
scaledCoords);
}
五、第四层:InputTransport 跨进程传输
文件:frameworks/native/libs/input/InputTransport.cpp
InputChannel 的创建与传递
应用调用 WindowManager.addView()
→ ViewRootImpl.setView()
→ mWindowSession.addToDisplayAsUser() Binder 调用 WMS
→ WMS.addWindow()
→ InputChannel::openInputChannelPair(name)
创建一对 Unix Domain Socket:
serverChannel → 注册到 InputDispatcher
clientChannel → 通过 Binder 传回应用进程
→ ViewRootImpl 用 clientChannel 创建 WindowInputEventReceiver
InputPublisher::publishMotionEvent()
status_t InputPublisher::publishMotionEvent(...) {
// 打包成 InputMessage 二进制结构
InputMessage msg;
msg.header.type = InputMessage::Type::MOTION;
msg.header.seq = seq;
msg.body.motion.action = action;
msg.body.motion.pointerCount = pointerCount;
// 填充所有 pointer 的坐标、压力、尺寸等数据
return mChannel->sendMessage(&msg);
}
InputChannel::sendMessage()
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
ssize_t nWrite;
do {
// MSG_DONTWAIT:非阻塞,缓冲区满时立即返回 EAGAIN
// MSG_NOSIGNAL:写入关闭的 fd 不触发 SIGPIPE 信号
nWrite = ::send(mFd.get(), msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return WOULD_BLOCK; // 缓冲区满,Dispatcher 暂停发送,等 finish 后继续
}
return OK;
}
六、第五层:应用进程接收
文件:frameworks/base/core/java/android/view/ViewRootImpl.java
InputEventReceiver:Socket 可读回调
// 底层 JNI 把 client fd 注册到主线程 Looper 的 epoll
// Socket 有数据时在主线程回调:
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event); // 子类 WindowInputEventReceiver 重写
}
// 处理完成后必须调用,通知 Dispatcher 继续发送
public final void finishInputEvent(InputEvent event, boolean handled) {
nativeFinishInputEvent(mReceiverPtr, seq, handled);
// JNI → InputConsumer::sendFinishedSignal()
// → InputChannel::sendMessage(FINISHED)
// → Dispatcher waitQueue 移除事件,ANR 计时取消
}
WindowInputEventReceiver
final class WindowInputEventReceiver extends InputEventReceiver {
@Override
public void onInputEvent(InputEvent event) {
// 兼容性处理(旧版 API 适配)
List<InputEvent> processedEvents =
mInputCompatProcessor.processMotionEventForCompatibility(event);
if (processedEvents != null) {
for (InputEvent e : processedEvents) {
enqueueInputEvent(e, this,
QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY, true);
}
} else {
enqueueInputEvent(event, this, 0, true);
// ↑ processImmediately=true 立即处理
}
}
@Override
public void onBatchedInputEventPending(int source) {
// 批量 MOVE 事件积累,注册 Choreographer 回调
// 下一帧 vsync 时统一处理,提升绘制效率
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
}
}
enqueueInputEvent() + deliverInputEvent()
void enqueueInputEvent(InputEvent event, InputEventReceiver receiver,
int flags, boolean processImmediately) {
// 构造 QueuedInputEvent 节点,加入链表
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
mPendingInputEventCount++;
if (processImmediately) {
doProcessInputEvents(); // 立即处理
} else {
scheduleProcessInputEvents(); // 发 Message 到主线程
}
}
void doProcessInputEvents() {
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
deliverInputEvent(q);
}
}
private void deliverInputEvent(QueuedInputEvent q) {
InputStage stage = q.shouldSkipIme()
? mFirstPostImeInputStage // 跳过 IME
: mFirstInputStage; // 从责任链头部开始
if (stage != null) {
handleWindowFocusChanged();
stage.deliver(q); // 进入 InputStage 责任链
} else {
finishInputEvent(q);
}
}
七、第六层:InputStage 责任链
责任链结构(ViewRootImpl.setView() 中构建)
mFirstInputStage:
① NativePreImeInputStage native 层预处理
↓
② ViewPreImeInputStage View 在 IME 前拦截按键
↓
③ ImeInputStage 发给输入法,IME 可消费
↓
④ EarlyPostImeInputStage 音量键/媒体键等全局快捷键
↓
⑤ ViewPostImeInputStage ←── 触摸事件主路径(最重要)
↓
⑥ NativePostImeInputStage native 后处理
↓
⑦ SyntheticInputStage 合成事件(轨迹球/无障碍注入)
InputStage 基类模板
abstract class InputStage {
private final InputStage mNext;
public final void deliver(QueuedInputEvent q) {
if ((q.mFlags & FLAG_FINISHED) != 0) {
forward(q); // 已处理,跳过传递
} else if (shouldDropInputEvent(q)) {
finish(q, false); // 丢弃(窗口不可见等)
} else {
apply(q, onProcess(q)); // 调用子类处理
}
}
protected int onProcess(QueuedInputEvent q) {
return FORWARD; // 默认不处理,向下传
}
protected void finish(QueuedInputEvent q, boolean handled) {
q.mFlags |= FLAG_FINISHED;
forward(q); // 标记完成后继续传递,让链路正常收尾
}
}
ViewPostImeInputStage:进入 View 树
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); // 游戏手柄等
}
}
}
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent) q.mEvent;
mAttachInfo.mHandlingPointerEvent = true;
boolean handled = mView.dispatchPointerEvent(event);
// mView 就是 DecorView,进入 View 树
maybeUpdatePointerIcon(event); // 更新鼠标光标
maybeUpdateTooltip(event); // 更新悬浮提示
mAttachInfo.mHandlingPointerEvent = false;
return handled ? FINISH_HANDLED : FORWARD;
}
}
八、第七层:DecorView → Activity → ViewGroup
文件:DecorView.java / Activity.java / PhoneWindow.java
入口调用链
// DecorView.java
public boolean dispatchTouchEvent(MotionEvent ev) {
final Window.Callback cb = mWindow.getCallback();
// cb 就是 Activity(implements Window.Callback)
return cb != null && !isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) // 先给 Activity
: super.dispatchTouchEvent(ev); // 直接走 ViewGroup
}
// Activity.java
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction(); // 用户交互回调(可重写,如重置屏保)
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true; // View 树消费了
}
return onTouchEvent(ev); // View 树没消费,Activity 最后兜底
}
// PhoneWindow.java
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event); // 绕回 DecorView
}
// DecorView.java
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event); // 调用 ViewGroup.dispatchTouchEvent()
}
九、第八层:ViewGroup.dispatchTouchEvent() 核心
文件:frameworks/base/core/java/android/view/ViewGroup.java
public boolean dispatchTouchEvent(MotionEvent ev) {
// ① 安全检查
if (!onFilterTouchEventForSecurity(ev)) {
return false;
// 窗口被遮挡(FLAG_WINDOW_IS_OBSCURED)
// 且开启了 filterTouchesWhenObscured → 拦截
}
// ② 是否拦截
final boolean intercepted;
if (actionMasked == ACTION_DOWN || mFirstTouchTarget != null) {
final boolean disallowIntercept =
(mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
// 子 View 通过 requestDisallowInterceptTouchEvent(true) 设置此标志
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev); // 默认返回 false
} else {
intercepted = false; // 子 View 禁止拦截
}
} else {
// 无子 View 接手 + 非 DOWN → 直接拦截,自己处理
intercepted = true;
}
// ③ ACTION_DOWN 时寻找处理者
if (!canceled && !intercepted) {
if (actionMasked == ACTION_DOWN || actionMasked == ACTION_POINTER_DOWN) {
// 反序遍历子 View(后绘制的在顶层,优先接收触摸)
final ArrayList<View> preorderedList = buildTouchDispatchChildList();
for (int i = childrenCount - 1; i >= 0; i--) {
final View child = getAndVerifyPreorderedView(preorderedList, i);
// 子 View 必须可见 + 触摸点在其范围内
if (!child.canReceivePointerEvents()
|| !isTransformedTouchPointInView(x, y, child, null)) {
continue;
}
// 已有其他手指在此 View,加入同一 TouchTarget
newTouchTarget = getTouchTarget(child);
if (newTouchTarget != null) {
newTouchTarget.pointerIdBits |= idBitsToAssign;
break;
}
// 尝试分发 DOWN 给子 View
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
// 子 View 消费了 DOWN → 记录为 mFirstTouchTarget
newTouchTarget = addTouchTarget(child, idBitsToAssign);
alreadyDispatchedToNewTouchTarget = true;
break;
}
// 没消费 → 继续遍历下一个
}
}
}
// ④ 分发后续事件
if (mFirstTouchTarget == null) {
// 无子 View 接手,自己处理
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
// MOVE/UP 直接发给 mFirstTouchTarget,不再遍历
TouchTarget target = mFirstTouchTarget;
while (target != null) {
final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted;
// intercepted=true:父 View 中途拦截,给子 View 发 CANCEL
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
if (cancelChild) {
// 发了 CANCEL,从链表移除
mFirstTouchTarget = target.next;
target.recycle();
}
target = target.next;
}
}
// ⑤ UP/CANCEL 时清理
if (canceled || actionMasked == ACTION_UP) {
resetTouchState(); // 清空 mFirstTouchTarget 链表
}
return handled;
}
dispatchTransformedTouchEvent():坐标变换 + 递归
private boolean dispatchTransformedTouchEvent(MotionEvent event,
boolean cancel, View child, int desiredPointerIdBits) {
if (cancel || oldAction == ACTION_CANCEL) {
event.setAction(ACTION_CANCEL);
if (child == null) return super.dispatchTouchEvent(event);
return child.dispatchTouchEvent(event); // 发 CANCEL
}
if (child == null) {
// 自己处理(ViewGroup 作为 View)
return super.dispatchTouchEvent(event);
}
// 坐标系转换到子 View 局部坐标
final float offsetX = mScrollX - child.mLeft;
final float offsetY = mScrollY - child.mTop;
event.offsetLocation(offsetX, offsetY);
boolean handled = child.dispatchTouchEvent(event); // 递归分发
// child 可能是 ViewGroup → 继续递归
// child 是 View → 进入 View.dispatchTouchEvent()
event.offsetLocation(-offsetX, -offsetY); // 还原坐标
return handled;
}
十、第九层:View.dispatchTouchEvent() + onTouchEvent()
文件:frameworks/base/core/java/android/view/View.java
public boolean dispatchTouchEvent(MotionEvent event) {
boolean result = false;
if (onFilterTouchEventForSecurity(event)) {
// 优先级① OnTouchListener(setOnTouchListener 注册)
if ((mViewFlags & ENABLED_MASK) == ENABLED
&& mListenerInfo != null
&& mListenerInfo.mOnTouchListener != null
&& mListenerInfo.mOnTouchListener.onTouch(this, event)) {
result = true;
// 返回 true → onTouchEvent 不再调用
}
// 优先级② onTouchEvent
if (!result && onTouchEvent(event)) {
result = true;
}
}
return result;
}
onTouchEvent():点击与长按的产生
public boolean onTouchEvent(MotionEvent event) {
if (!isClickable() && !isLongClickable()) return false;
// DISABLED 的 View 也消费事件(但不响应)
if ((viewFlags & ENABLED_MASK) == DISABLED) return clickable;
// TouchDelegate:扩大点击热区
if (mTouchDelegate != null && mTouchDelegate.onTouchEvent(event)) {
return true;
}
switch (action) {
case ACTION_DOWN:
boolean isInScrollingContainer = isInScrollingContainer();
if (isInScrollingContainer) {
// 滚动容器内:延迟 100ms 确认(避免滚动误触)
mPrivateFlags |= PFLAG_PREPRESSED;
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
} else {
// 立即 PRESSED 状态(触发波纹视觉反馈)
setPressed(true, x, y);
// 开启长按计时器(默认 400ms)
checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y, ...);
}
break;
case ACTION_MOVE:
drawableHotspotChanged(x, y); // 波纹中心跟手指
if (!pointInView(x, y, touchSlop)) {
// 滑出 touchSlop 范围(默认 8dp)
removeTapCallback(); // 取消 TAP
removeLongPressCallback(); // 取消长按
setPressed(false); // 取消按下状态
}
break;
case ACTION_UP:
if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
removeLongPressCallback();
// post 到主线程下一帧执行(让波纹先显示)
if (!post(mPerformClick)) {
performClickInternal(); // post 失败则同步执行
}
}
setPressed(false);
}
break;
case ACTION_CANCEL:
setPressed(false);
removeTapCallback();
removeLongPressCallback();
break;
}
return true;
}
// performClick() 触发 onClick
public boolean performClick() {
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this); // ← onClick 最终在这里调用!
return true;
}
return false;
}
// 长按检测 Runnable
private final class CheckForLongPress implements Runnable {
public void run() {
if (isPressed() && mParent != null) {
if (performLongClick(mX, mY)) {
mHasPerformedLongPress = true;
// 标记已长按,ACTION_UP 时不再触发 onClick
}
}
}
}
十一、finish 回执:ANR 计时取消
// ViewRootImpl.java
void finishInputEvent(QueuedInputEvent q) {
boolean handled = (q.mFlags & FLAG_FINISHED_HANDLED) != 0;
q.mReceiver.finishInputEvent(q.mEvent, handled);
}
// InputEventReceiver.java
public final void finishInputEvent(InputEvent event, boolean handled) {
nativeFinishInputEvent(mReceiverPtr, seq, handled);
}
// JNI → InputConsumer::sendFinishedSignal(seq, handled)
// → InputChannel::sendMessage({FINISHED, seq, handled})
// → send(client fd, msg)
// Dispatcher 侧收到 FINISHED:
// handleReceiveCallback()
// → 从 waitQueue 移除对应 seq 的事件
// → ANR 计时取消(dispatchEntry->timeoutTime 失效)
// → startDispatchCycleLocked() 继续发下一个事件
十二、完整链路总图
触摸屏硬件中断
↓
内核 input 子系统 → /dev/input/eventX
↓
EventHub::getEvents()
epoll_wait 阻塞监听 → 有事件唤醒
read(device->fd) → input_event[]
转换成 RawEvent(加 deviceId/readTime)
↓
InputReader::loopOnce()
processEventsLocked()
同一设备事件打包批量处理
→ TouchInputMapper
多点协议解析、坐标归一化、屏幕方向校正
→ 生成 NotifyMotionArgs
mNextListener.notify(args)(锁外)
↓
InputListenerInterface::notify()
std::visit 识别类型 → notifyMotion()
↓
InputDispatcher::notifyMotion()
validateMotionEvent() 合法性校验
interceptMotionBeforeQueueing() Policy 拦截
filterInputEvent() InputFilter 过滤
构造 MotionEntry → enqueueInboundEventLocked()
mInboundQueue.push_back()
MOVE 堆积时跳帧优化
mLooper->wake() 唤醒 Dispatcher 线程
↓
InputDispatcher 线程从 pollOnce() 醒来
dispatchOnceInnerLocked()
mInboundQueue.pop_front()
过期/AppSwitch 丢弃判断
dispatchMotionLocked()
isPointerEvent ?
→ findTouchedWindowTargetsLocked() 遍历窗口Z序找命中窗口
→ findFocusedWindowTargetLocked() 键盘找焦点窗口
addGlobalMonitoringTargetsLocked() 加入无障碍等全局监听
dispatchEventLocked(inputTargets)
processInteractionsLocked() 焦点转移处理
pokeUserActivityLocked() 通知 PowerManager
for each inputTarget:
prepareDispatchCycleLocked()
splitMotionEvent() 多指分割
enqueueDispatchEntriesLocked()
startDispatchCycleLocked()
timeoutTime = now + 5s ← ANR 计时开始
publishMotionEvent()
坐标缩放 + HMAC 签名
inputPublisher.publishMotionEvent()
InputMessage 序列化
InputChannel::sendMessage()
send(server fd, msg)
outboundQueue → waitQueue
↓ Unix Domain Socket
应用进程 client fd epoll 可读(主线程)
InputEventReceiver::dispatchInputEvent() JNI 回调
WindowInputEventReceiver::onInputEvent()
ViewRootImpl::enqueueInputEvent()
构造 QueuedInputEvent 链表
doProcessInputEvents()
deliverInputEvent()
↓ InputStage 责任链
NativePreImeInputStage → ViewPreImeInputStage → ImeInputStage
→ EarlyPostImeInputStage → ViewPostImeInputStage
processPointerEvent()
mView.dispatchPointerEvent() mView = DecorView
↓
DecorView.dispatchTouchEvent()
cb.dispatchTouchEvent() cb = Activity
↓
Activity.dispatchTouchEvent()
onUserInteraction()
getWindow().superDispatchTouchEvent()
↓
PhoneWindow → DecorView.superDispatchTouchEvent()
↓
ViewGroup.dispatchTouchEvent()
onFilterTouchEventForSecurity() 安全检查
onInterceptTouchEvent() 父 View 拦截判断
ACTION_DOWN: 反序遍历子 View
isTransformedTouchPointInView() 坐标命中
dispatchTransformedTouchEvent()
event.offsetLocation() 坐标系转换
child.dispatchTouchEvent() 递归
ACTION_MOVE/UP: 直接发 mFirstTouchTarget
intercepted=true: 发 CANCEL 给子 View
↓
View.dispatchTouchEvent()
OnTouchListener.onTouch() 优先级①
onTouchEvent() 优先级②
DOWN → setPressed(波纹) + 长按计时(400ms)
MOVE → 检查 touchSlop(8dp),超出取消长按
UP → performClick() → onClick()
CANCEL → 清理所有状态
↓
finishInputEvent()
InputEventReceiver.finishInputEvent()
JNI → InputConsumer::sendFinishedSignal()
InputChannel::sendMessage(FINISHED)
Dispatcher::handleReceiveCallback()
waitQueue 移除事件
ANR 计时取消
startDispatchCycleLocked() 继续下一个
十三、关键机制总结
ANR 触发机制
startDispatchCycleLocked() 设置:
dispatchEntry->timeoutTime = currentTime + 5秒
事件进入 waitQueue 等待 finish 回执
processAnrsLocked() 每次循环检查:
now >= dispatchEntry->timeoutTime → 触发 ANR
→ onAnrLocked() → 弹出 ANR 对话框 / 结束进程
mFirstTouchTarget 决定事件归属
ACTION_DOWN:遍历子 View,找到第一个消费的记为 mFirstTouchTarget
ACTION_MOVE/UP:直接发给 mFirstTouchTarget,不重新遍历
→ 子 View 的 onTouchEvent(DOWN) 返回 false
→ mFirstTouchTarget = null
→ 后续 MOVE/UP 全由父 ViewGroup 的 onTouchEvent 处理
事件优先级
高 ─────────────────────────────────────── 低
TouchDelegate > OnTouchListener > onTouchEvent > onClick/onLongClick
(扩大热区) (set方法注册) (重写方法) (最终回调)
防死锁设计
InputReader:
getEvents() 无锁(阻塞等待期间允许其他线程访问)
notify() 无锁(Dispatcher 回调可能反查 InputReader)
InputDispatcher:
Policy 拦截 锁外(可能做耗时 Binder 调用)
入队操作 锁内(修改队列必须加锁)
发送事件 锁外(Dispatcher 回调可能反查自身)
十四、关键常量速查
| 常量 | 值 | 说明 |
|---|---|---|
| Input ANR 超时 | 5 秒 | startDispatchCycleLocked 设置 |
| 前台 Service ANR | 20 秒 | ActiveServices |
| 前台 Broadcast ANR | 10 秒 | BroadcastQueue |
| longPressTimeout | 400ms | 长按触发时间(Android 9+) |
| tapTimeout | 100ms | 滚动容器内确认点击延迟 |
| touchSlop | 8dp | 超出此范围视为滑动而非点击 |
| Binder 线程数 | 最多 16 | 1主线程 + 15个 Binder 线程 |
十五、关键源码文件索引
| 文件 | 路径 | 作用 |
|---|---|---|
| EventHub.cpp | inputflinger/reader/EventHub.cpp |
epoll 读取硬件事件 |
| InputReader.cpp | inputflinger/reader/InputReader.cpp |
事件加工主循环 |
| TouchInputMapper.cpp | inputflinger/reader/mapper/ |
触摸协议解析、坐标变换 |
| InputListener.cpp | inputflinger/InputListener.cpp |
notify() 类型分发 |
| InputDispatcher.cpp | inputflinger/dispatcher/InputDispatcher.cpp |
路由、ANR、发送 |
| InputTransport.cpp | libs/input/InputTransport.cpp |
Socket 收发、序列化 |
| InputChannel.cpp | libs/input/InputChannel.cpp |
Unix Socket 封装 |
| InputEventReceiver.java | core/java/android/view/InputEventReceiver.java |
应用侧接收入口 |
| ViewRootImpl.java | core/java/android/view/ViewRootImpl.java |
入队、InputStage 责任链 |
| DecorView.java | core/java/com/android/internal/policy/DecorView.java |
窗口根 View |
| Activity.java | core/java/android/app/Activity.java |
dispatchTouchEvent 兜底 |
| ViewGroup.java | core/java/android/view/ViewGroup.java |
核心分发、拦截、寻找目标 |
| View.java | core/java/android/view/View.java |
onClick/onLongClick 产生 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)