概述
InputChannel是Android输入系统中负责跨进程事件传输的核心组件,它建立了InputDispatcher(SystemServer进程)与应用程序(App进程)之间的高效通信通道。本文深入分析InputChannel的实现机制,包括socket pair通信、事件传输协议、以及应用层接收机制。
AOSP源码 基于Android 7.0
InputChannel整体架构
┌─────────────────────────────────────────────────────────────┐
│ SystemServer 进程 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ InputDispatcher │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ InputPublisher │ │ │
│ │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ │ Server Socket (写端) │ │ │ │
│ │ │ └─────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘││ Unix Domain Socket Pair│ (SOCK_SEQPACKET)│
┌─────────────────────────────────────────────────────────────┐
│ Application 进程 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ViewRootImpl │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ InputEventReceiver │ │ │
│ │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ │ InputConsumer │ │ │ │
│ │ │ │ ┌─────────────────────────────┐ │ │ │ │
│ │ │ │ │ Client Socket (读端) │ │ │ │ │
│ │ │ │ └─────────────────────────────┘ │ │ │ │
│ │ │ └─────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
1. InputChannel的创建和注册
1.1 创建流程
InputChannel的创建是在应用窗口添加到WindowManager时完成的:
应用启动/窗口创建│▼
Activity.setContentView()│▼
ViewRootImpl.setView()│▼
WindowManagerService.addWindow()│▼
InputChannel.openInputChannelPair()│▼
创建Socket Pair
├─ Server Socket → InputDispatcher
└─ Client Socket → Application
1.2 Socket Pair创建代码
文件路径: frameworks/native/libs/input/InputTransport.cpp
status_t InputChannel::openInputChannelPair(const String8& name,sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {int sockets[2];// 创建Unix域套接字对,使用SOCK_SEQPACKET确保消息边界if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {status_t result = -errno;ALOGE("channel '%s' ~ Could not create socket pair. errno=%d",name.string(), errno);outServerChannel.clear();outClientChannel.clear();return result;}// 设置socket缓冲区大小为32KB,足够存储多个大型触摸事件int bufferSize = SOCKET_BUFFER_SIZE; // 32 * 1024setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));// 创建服务端通道(InputDispatcher使用)String8 serverChannelName = name;serverChannelName.append(" (server)");outServerChannel = new InputChannel(serverChannelName, sockets[0]);// 创建客户端通道(应用程序使用)String8 clientChannelName = name;clientChannelName.append(" (client)");outClientChannel = new InputChannel(clientChannelName, sockets[1]);return OK;
}
1.3 InputChannel构造函数
InputChannel::InputChannel(const String8& name, int fd) :mName(name), mFd(fd) {// 设置为非阻塞模式,防止发送/接收操作阻塞线程int result = fcntl(mFd, F_SETFL, O_NONBLOCK);LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket ""non-blocking. errno=%d", mName.string(), errno);
}
1.4 通道注册到InputDispatcher
// frameworks/native/services/inputflinger/InputDispatcher.cpp
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {{ // acquire lockAutoMutex _l(mLock);// 检查通道是否已经注册if (getConnectionIndexLocked(inputChannel) >= 0) {ALOGW("Attempted to register already registered input channel '%s'",inputChannel->getName().string());return BAD_VALUE;}// 创建Connection对象,管理与应用的连接sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);int fd = inputChannel->getFd();mConnectionsByFd.add(fd, connection);// 将文件描述符添加到Looper中监听mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);} // release lock// 唤醒Looper以便立即开始监听新连接mLooper->wake();return OK;
}
2. 事件传输协议
2.1 InputMessage结构
InputChannel使用统一的InputMessage结构来传输不同类型的事件:
字段 | 类型 | 说明 |
---|---|---|
Header | struct | 消息头,包含类型和填充 |
Body | union | 消息体,根据类型包含不同事件数据 |
2.2 消息类型
// frameworks/native/include/input/InputTransport.h
struct InputMessage {enum {TYPE_KEY = 1, // 按键事件TYPE_MOTION = 2, // 运动事件(触摸、鼠标等)TYPE_FINISHED = 3, // 事件处理完成确认};struct Header {uint32_t type; // 消息类型uint32_t padding; // 对齐填充} header;// 消息体必须8字节对齐union Body {struct Key {uint32_t seq; // 序列号nsecs_t eventTime __attribute__((aligned(8))); // 事件时间int32_t deviceId; // 设备IDint32_t source; // 事件源int32_t action; // 动作int32_t flags; // 标志int32_t keyCode; // 键码int32_t scanCode; // 扫描码int32_t metaState; // 修饰键状态int32_t repeatCount; // 重复次数nsecs_t downTime __attribute__((aligned(8))); // 按下时间} key;struct Motion {uint32_t seq; // 序列号nsecs_t eventTime __attribute__((aligned(8))); // 事件时间int32_t deviceId; // 设备IDint32_t source; // 事件源int32_t action; // 动作int32_t actionButton; // 按键int32_t flags; // 标志int32_t metaState; // 修饰键状态int32_t buttonState; // 按键状态int32_t edgeFlags; // 边缘标志nsecs_t downTime __attribute__((aligned(8))); // 按下时间float xOffset; // X偏移float yOffset; // Y偏移float xPrecision; // X精度float yPrecision; // Y精度uint32_t pointerCount; // 触点数量struct Pointer {PointerProperties properties; // 触点属性PointerCoords coords; // 触点坐标} pointers[MAX_POINTERS]; // 触点数组} motion;struct Finished {uint32_t seq; // 序列号bool handled; // 是否已处理} finished;} __attribute__((aligned(8))) body;
};
2.3 消息大小计算
size_t InputMessage::size() const {switch (header.type) {case TYPE_KEY:return sizeof(Header) + body.key.size();case TYPE_MOTION:return sizeof(Header) + body.motion.size();case TYPE_FINISHED:return sizeof(Header) + body.finished.size();}return sizeof(Header);
}// Motion消息的动态大小计算
inline size_t Motion::size() const {return sizeof(Motion) - sizeof(Pointer) * MAX_POINTERS+ sizeof(Pointer) * pointerCount;
}
3. 事件发送:InputPublisher
3.1 InputPublisher架构
InputPublisher负责将InputDispatcher的事件通过InputChannel发送给应用:
InputDispatcher::startDispatchCycleLocked()│▼
Connection::inputPublisher.publishKeyEvent()│▼ 构造InputMessage
填充消息头和消息体│▼ InputChannel::sendMessage()
通过socket发送消息│▼
应用端InputChannel接收
3.2 按键事件发布
// frameworks/native/libs/input/InputTransport.cpp
status_t InputPublisher::publishKeyEvent(uint32_t seq,int32_t deviceId,int32_t source,int32_t action,int32_t flags,int32_t keyCode,int32_t scanCode,int32_t metaState,int32_t repeatCount,nsecs_t downTime,nsecs_t eventTime) {// 构造按键事件消息InputMessage msg;msg.header.type = InputMessage::TYPE_KEY;msg.body.key.seq = seq;msg.body.key.eventTime = eventTime;msg.body.key.deviceId = deviceId;msg.body.key.source = source;msg.body.key.action = action;msg.body.key.flags = flags;msg.body.key.keyCode = keyCode;msg.body.key.scanCode = scanCode;msg.body.key.metaState = metaState;msg.body.key.repeatCount = repeatCount;msg.body.key.downTime = downTime;// 通过InputChannel发送消息return mChannel->sendMessage(&msg);
}
3.3 运动事件发布
status_t InputPublisher::publishMotionEvent(uint32_t seq,int32_t deviceId,int32_t source,int32_t action,int32_t actionButton,int32_t flags,int32_t edgeFlags,int32_t metaState,int32_t buttonState,float xOffset,float yOffset,float xPrecision,float yPrecision,nsecs_t downTime,nsecs_t eventTime,uint32_t pointerCount,const PointerProperties* pointerProperties,const PointerCoords* pointerCoords) {// 检查参数有效性if (pointerCount > MAX_POINTERS || pointerCount < 1) {return BAD_VALUE;}// 构造运动事件消息InputMessage msg;msg.header.type = InputMessage::TYPE_MOTION;msg.body.motion.seq = seq;msg.body.motion.eventTime = eventTime;msg.body.motion.deviceId = deviceId;msg.body.motion.source = source;msg.body.motion.action = action;msg.body.motion.actionButton = actionButton;msg.body.motion.flags = flags;msg.body.motion.metaState = metaState;msg.body.motion.buttonState = buttonState;msg.body.motion.edgeFlags = edgeFlags;msg.body.motion.downTime = downTime;msg.body.motion.xOffset = xOffset;msg.body.motion.yOffset = yOffset;msg.body.motion.xPrecision = xPrecision;msg.body.motion.yPrecision = yPrecision;msg.body.motion.pointerCount = pointerCount;// 复制触点数据for (uint32_t i = 0; i < pointerCount; i++) {msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);}// 通过InputChannel发送消息return mChannel->sendMessage(&msg);
}
3.4 底层Socket发送
status_t InputChannel::sendMessage(const InputMessage* msg) {size_t msgLength = msg->size();ssize_t nWrite;// 使用MSG_DONTWAIT确保非阻塞发送,MSG_NOSIGNAL避免SIGPIPE信号do {nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);} while (nWrite == -1 && errno == EINTR);if (nWrite < 0) {int error = errno;if (error == EAGAIN || error == EWOULDBLOCK) {return WOULD_BLOCK;}if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {return DEAD_OBJECT;}return -error;}if (size_t(nWrite) != msgLength) {return DEAD_OBJECT;}return OK;
}
4. 事件接收:InputConsumer
4.1 应用层接收架构
应用端通过InputEventReceiver接收事件:
Socket数据到达│▼ Looper监听fd可读
Native InputConsumer回调│▼ 解析InputMessage
创建Java InputEvent对象│▼ 调用Java回调
InputEventReceiver.onInputEvent()│▼ 事件分发
ViewRootImpl处理事件
4.2 InputEventReceiver创建
文件路径: frameworks/base/core/java/android/view/InputEventReceiver.java
public abstract class InputEventReceiver {// 指向native接收器对象的指针private long mReceiverPtr;// 保持对输入通道和消息队列的引用,防止被垃圾回收private InputChannel mInputChannel;private MessageQueue mMessageQueue;// 序列号映射表:从InputEvent序列号到调度器序列号private final SparseIntArray mSeqMap = new SparseIntArray();/*** 创建绑定到指定输入通道的事件接收器*/public InputEventReceiver(InputChannel inputChannel, Looper looper) {if (inputChannel == null) {throw new IllegalArgumentException("inputChannel must not be null");}if (looper == null) {throw new IllegalArgumentException("looper must not be null");}mInputChannel = inputChannel;mMessageQueue = looper.getQueue();// 初始化native接收器,传入弱引用避免内存泄漏mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),inputChannel, mMessageQueue);mCloseGuard.open("dispose");}
}
4.3 Native层InputConsumer
// frameworks/native/libs/input/InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory,bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {*outEvent = NULL;*outSeq = 0;while (!*outEvent) {if (mMsgDeferred) {// 处理延迟的消息mMsgDeferred = false;} else {// 接收新消息status_t result = mChannel->receiveMessage(&mMsg);if (result) {// 如果没有消息可读,则返回if (result == WOULD_BLOCK) {if (!consumeBatches) {result = OK;}}return result;}}switch (mMsg.header.type) {case InputMessage::TYPE_KEY: {KeyEvent* keyEvent = factory->createKeyEvent();if (!keyEvent) return NO_MEMORY;// 初始化按键事件initializeKeyEvent(keyEvent, &mMsg);*outSeq = mMsg.body.key.seq;*outEvent = keyEvent;break;}case InputMessage::TYPE_MOTION: {ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);if (batchIndex >= 0) {// 添加到现有批次Batch& batch = mBatches.editItemAt(batchIndex);if (canAddSample(batch, &mMsg)) {batch.samples.push();addSample(batch, &mMsg);break;}}// 开始新批次或立即传递事件MotionEvent* motionEvent = factory->createMotionEvent();if (!motionEvent) return NO_MEMORY;updateTouchState(&mMsg);initializeMotionEvent(motionEvent, &mMsg);*outSeq = mMsg.body.motion.seq;*outEvent = motionEvent;if (batchIndex < 0) {// 创建新批次用于后续事件mBatches.push();Batch& batch = mBatches.editTop();batch.samples.push();addSample(batch, &mMsg);}break;}default:ALOGE("channel received unknown message type %d", mMsg.header.type);return UNKNOWN_ERROR;}}return OK;
}
4.4 底层Socket接收
status_t InputChannel::receiveMessage(InputMessage* msg) {ssize_t nRead;// 非阻塞接收消息do {nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);} while (nRead == -1 && errno == EINTR);if (nRead < 0) {int error = errno;if (error == EAGAIN || error == EWOULDBLOCK) {return WOULD_BLOCK;}if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {return DEAD_OBJECT;}return -error;}if (nRead == 0) { // EOF检查return DEAD_OBJECT;}if (!msg->isValid(nRead)) {return BAD_VALUE;}return OK;
}
5. 事件处理完成确认机制
5.1 确认流程
为了实现ANR检测和流量控制,InputChannel使用确认机制:
应用处理完事件│▼ InputEventReceiver.finishInputEvent()
发送TYPE_FINISHED消息│▼ InputChannel传输
InputDispatcher接收确认│▼ Connection.waitQueue
移除已完成的事件
5.2 应用层发送确认
// frameworks/base/core/java/android/view/InputEventReceiver.java
public final void finishInputEvent(InputEvent event, boolean handled) {if (event == null) {throw new IllegalArgumentException("event must not be null");}if (mReceiverPtr == 0) {Log.w(TAG, "Attempted to finish an input event but the input event "+ "receiver has already been disposed.");} else {// 从序列号映射表中查找调度器序列号int index = mSeqMap.indexOfKey(event.getSequenceNumber());if (index < 0) {Log.w(TAG, "Attempted to finish an input event that is not in progress.");} else {int seq = mSeqMap.valueAt(index);mSeqMap.removeAt(index);// 调用native方法发送确认nativeFinishInputEvent(mReceiverPtr, seq, handled);}}// 回收事件对象event.recycleIfNeededAfterDispatch();
}
5.3 Native层发送确认
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {InputMessage msg;msg.header.type = InputMessage::TYPE_FINISHED;msg.body.finished.seq = seq;msg.body.finished.handled = handled;return mChannel->sendMessage(&msg);
}
5.4 InputDispatcher处理确认
void InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {InputDispatcher* d = static_cast<InputDispatcher*>(data);{ // acquire lockAutoMutex _l(d->mLock);ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);if (connectionIndex < 0) {return; // 连接已移除}sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);if (events & ALOOPER_EVENT_INPUT) {nsecs_t currentTime = now();bool gotOne = false;status_t status;for (;;) {InputMessage msg;status = connection->inputChannel->receiveMessage(&msg);if (status) {break;}if (msg.header.type == InputMessage::TYPE_FINISHED) {d->finishDispatchCycleLocked(currentTime, connection, msg.body.finished.seq, msg.body.finished.handled);gotOne = true;}}if (gotOne) {d->runCommandsLockedInterruptible();}}} // release lock
}
6. 批量处理和性能优化
6.1 事件批量处理
为了优化性能,InputChannel支持触摸事件的批量处理:
优化技术 | 实现方式 | 性能收益 |
---|---|---|
事件批量 | 多个MOVE事件合并 | 减少跨进程调用次数 |
延迟传递 | 批量事件延迟到帧边界 | 与UI渲染同步 |
预测采样 | 根据历史数据预测触点位置 | 减少感知延迟 |
6.2 触摸重采样
// frameworks/native/libs/input/InputTransport.cpp
// 重采样常量
static const nsecs_t RESAMPLE_LATENCY = 5 * NANOS_PER_MS; // 5ms延迟
static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS; // 最小间隔2ms
static const nsecs_t RESAMPLE_MAX_DELTA = 20 * NANOS_PER_MS; // 最大间隔20ms
static const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS; // 最大预测8msbool InputConsumer::shouldResampleTool(int32_t toolType) {return toolType == AMOTION_EVENT_TOOL_TYPE_FINGER|| toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
}void InputConsumer::resampleTouchState(nsecs_t frameTime, MotionEvent* event,const InputMessage* next) {if (!mResampleTouch || !(event->getSource() & AINPUT_SOURCE_CLASS_POINTER)|| event->getAction() != AMOTION_EVENT_ACTION_MOVE) {return;}// 计算重采样时间nsecs_t sampleTime = frameTime - RESAMPLE_LATENCY;// 执行线性插值重采样uint32_t pointerCount = event->getPointerCount();for (uint32_t i = 0; i < pointerCount; i++) {uint32_t id = event->getPointerId(i);// 获取历史样本数据nsecs_t prevTime = event->getHistoricalEventTime(event->getHistorySize() - 1);nsecs_t nextTime = next->body.motion.eventTime;if (sampleTime > prevTime && sampleTime < nextTime) {// 计算插值因子float alpha = float(sampleTime - prevTime) / float(nextTime - prevTime);// 插值计算新坐标float prevX = event->getHistoricalX(i, event->getHistorySize() - 1);float prevY = event->getHistoricalY(i, event->getHistorySize() - 1);float nextX = next->body.motion.pointers[i].coords.getX();float nextY = next->body.motion.pointers[i].coords.getY();float newX = lerp(prevX, nextX, alpha);float newY = lerp(prevY, nextY, alpha);// 更新事件坐标event->setXOffset(event->getXOffset() + newX - prevX);event->setYOffset(event->getYOffset() + newY - prevY);}}
}
6.3 内存管理优化
class InputConsumer {
private:// 批量事件管理struct Batch {Vector<InputMessage> samples; // 样本缓存};Vector<Batch> mBatches; // 批量缓存// 对象池化static const size_t MAX_RECYCLED_EVENTS = 4;KeyEvent* mRecycledKeyEvents[MAX_RECYCLED_EVENTS];MotionEvent* mRecycledMotionEvents[MAX_RECYCLED_EVENTS];// 统计信息TouchState mTouchState; // 触摸状态跟踪InputMessage mMsg; // 消息缓冲区bool mMsgDeferred; // 延迟标志
};
7. 错误处理和连接管理
7.1 连接状态管理
状态 | 说明 | 处理方式 |
---|---|---|
NORMAL | 正常连接 | 正常收发消息 |
BROKEN | 连接断开 | 停止发送,清理资源 |
ZOMBIE | 僵尸状态 | 等待应用退出 |
7.2 错误处理机制
void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,const sp<Connection>& connection, bool notify) {// 标记连接为断开状态connection->status = Connection::STATUS_BROKEN;// 清理待发送队列drainDispatchQueueLocked(&connection->outboundQueue);drainDispatchQueueLocked(&connection->waitQueue);// 生成取消事件通知其他窗口if (notify) {synthesizeCancelationEventsForConnectionLocked(connection,CancelationOptions(CancelationOptions::CANCEL_ALL_EVENTS,"broken input channel"));}// 从连接映射中移除unregisterInputChannelLocked(connection->inputChannel, notify);
}
7.3 超时检测
String8 InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,const char* targetType) {// 检查连接状态ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel());if (connectionIndex < 0) {return String8::format("Window is not registered");}sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);if (connection->status != Connection::STATUS_NORMAL) {return String8::format("Window connection is broken");}// 检查等待队列长度和时间if (!connection->waitQueue.isEmpty()) {const DispatchEntry* head = connection->waitQueue.head;nsecs_t waitDuration = currentTime - head->deliveryTime;if (waitDuration > STREAM_AHEAD_EVENT_TIMEOUT) {return String8::format("Waiting too long to send non-key event");}}return String8::empty();
}
8. 调试和监控
8.1 调试开关
// frameworks/native/libs/input/InputTransport.cpp
#define DEBUG_CHANNEL_MESSAGES 0 // 通道消息调试
#define DEBUG_CHANNEL_LIFECYCLE 0 // 通道生命周期调试
#define DEBUG_TRANSPORT_ACTIONS 0 // 传输动作调试
#define DEBUG_RESAMPLING 0 // 重采样调试
8.2 性能监控
监控指标 | 获取方式 | 用途 |
---|---|---|
消息发送延迟 | sendMessage耗时 | 性能分析 |
批量事件数量 | batch.samples.size() | 优化效果评估 |
连接状态 | Connection::status | 健康检查 |
重采样统计 | resample计数器 | 渲染性能分析 |
8.3 常用调试命令
# 查看InputChannel连接状态
adb shell dumpsys input# 监控socket使用情况
adb shell cat /proc/net/unix | grep input# 查看应用Input事件处理
adb shell dumpsys activity | grep -A5 -B5 Input# 监控触摸重采样
adb shell setprop debug.choreographer.skipwarning 0
9. 与其他组件的协作
9.1 WindowManager集成
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,WindowManager.LayoutParams attrs, int viewVisibility, int displayId,Rect outContentInsets, Rect outStableInsets, Rect outOutsets,InputChannel outInputChannel) {// 创建InputChannel对final String name = win.makeInputChannelName();InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);win.setInputChannel(inputChannels[0]);// 注册到InputDispatchermInputManager.registerInputChannel(inputChannels[0], win.mInputWindowHandle);// 返回客户端InputChannelif (outInputChannel != null) {inputChannels[1].transferTo(outInputChannel);inputChannels[1].dispose();}
}
9.2 ViewRootImpl集成
// frameworks/base/core/java/android/view/ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {super(inputChannel, looper);}@Overridepublic void onInputEvent(InputEvent event) {enqueueInputEvent(event, this, 0, true);}@Overridepublic void onBatchedInputEventPending() {if (mUnbufferedInputDispatch) {super.onBatchedInputEventPending();} else {scheduleConsumeBatchedInput();}}
}public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {if (mInputChannel != null) {if (mInputQueueCallback != null) {mInputQueue = new InputQueue();mInputQueueCallback.onInputQueueCreated(mInputQueue);}mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,Looper.myLooper());}
}
10. 总结
10.1 InputChannel核心价值
- 高效通信: 基于Unix域socket的低延迟跨进程通信
- 消息协议: 统一的InputMessage结构支持多种事件类型
- 流量控制: 通过确认机制实现ANR检测和流量控制
- 性能优化: 批量处理、重采样等技术提升用户体验
- 可靠性: 完善的错误处理和连接管理机制
10.2 技术特点
- 零拷贝传输: 使用SOCK_SEQPACKET确保消息边界
- 非阻塞IO: 所有socket操作都是非阻塞的
- 内存对齐: 消息结构针对64位系统优化对齐
- 批量优化: 触摸事件的智能批量处理
- 预测性重采样: 减少触摸延迟的关键技术
10.3 系统架构意义
InputChannel作为Android输入系统的通信基础设施:
- 解耦设计: 分离了系统服务和应用程序的输入处理
- 性能保障: 确保输入事件的低延迟传输
- 扩展性: 支持多种输入设备和事件类型
- 可维护性: 清晰的接口和错误处理机制
相关文件路径
核心实现文件
frameworks/native/libs/input/InputTransport.cpp
- InputChannel核心实现frameworks/native/include/input/InputTransport.h
- InputChannel头文件frameworks/base/core/java/android/view/InputChannel.java
- Java层InputChannelframeworks/base/core/java/android/view/InputEventReceiver.java
- 事件接收器
JNI层文件
frameworks/base/core/jni/android_view_InputChannel.cpp
- InputChannel JNIframeworks/base/core/jni/android_view_InputEventReceiver.cpp
- InputEventReceiver JNI
测试文件
frameworks/native/libs/input/tests/InputChannel_test.cpp
- InputChannel单元测试frameworks/base/core/tests/coretests/src/android/view/InputChannelTest.java
- Java层测试