概述
Android 输入系统的工作原理概括来说,内核将原始事件写入到设备节点中,InputReader 不断地通过 EventHub 将原始事件取出来并翻译加工成 Android 输入事件,然后交给 InputDispatcher。
InputDispatcher 根据 WMS 提供的窗口信息将事件交给合适的窗口。窗口的 ViewRootImpl 对象再沿着控件树将事件派发给感兴趣的控件。控件对其收到的事件作出响应,更新自己的画面、执行特定的动作
概念解释
InputManagerService(IMS):Android 系统服务,分为 Java 层和 Native 层两部分,Java 层负责与 WMS 通信,而 Native 层则是 InputReader 和 InputDispatcher 两个输入系统关键组件的运行容器;
WindowManagerService(WMS):它并不是输入系统的一员,新建窗口时,WMS 为新窗口和 IMS 创建了事件传递所用的通道,会将窗口的可点击区域,焦点窗口等信息实时更新到 IMS 的 InputDispatcher 中,使得 InputDispatcher 可以正确将事件派发到指定窗口;
EventHub:直接访问所有的设备节点,通过 getEvents() 函数将所有输入系统相关的待处理的底层事件返回给使用者,包括原始输入事件,设备节点的增删等;
InputReader:运行在一个独立的线程中,负责管理输入设备的列表和配置,以及进行输入事件的加工处理,它通过其线程循环不断地通过 getEvents() 函数从 EventHub 中将事件取出并进行处理,对于设备节点的增删事件,它会更新输入设备列表与配置;对于原始输入事件,InputReader对其进行翻译,组装,封装为包含更多信息,更多可读性的输入事件,然后交给InputDispatcher进行派发;
InputDispatcher:运行于一个独立的线程中,InputDispatcher 中保管来自 WMS 的所有窗口的信息,收到 InputReader 的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口;
ViewRootImpl:对某些窗口,如 SurfaceView 的窗口来说,窗口就是输入事件派发的终点,而对其他的如Activity,对话框等使用了 Android 控件系统的窗口来说,输入事件的终点是控件;
Input 系统流程
服务端
Input 系统初始化 IMS
SystemServer中 的 ServerThread 线程中启动 InputManagerService
- 创建 IMS 对象
- 创建 NativeInputManager 对象,此对象将是 Native 层组件与 Java 层 IMS 进行通信的桥梁
- 创建 Native 层的 InputManager,创建 InputDispatcher、InputReader、EventHub
- 将 IMS 添加到服务中心
- 调用 IMS 对象的 start() 函数完成 InputDispatcherThread 、InputReaderThread 的创建和启动
- InputReader 在其线程循环中不断地从 EventHub 中抽取原始输入事件,进行加工处理后将加工所得的事件放入 InputDispatcher 的派发发队列中
- InputDispatcher 则在其线程循环中将派发队列中的事件取出,查找合适的窗口,将事件写入到窗口的事件接收管道中
- 窗口事件接收线程的 Looper 从管道中将事件取出,交由事件处理函数进行事件响应
暂时无法在飞书文档外展示此内容
源码分析
SystemServer.java {
public static void main(String[] args) {
new SystemServer().run();
}
@Override
public void run() {
startOtherServices(t);
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
InputManagerService inputManager = null;
inputManager = new InputManagerService(context);
// 将IMS发布给ServiceManager,以便其他人可以访问IMS提供的接口
ServiceManager.addService(Context.INPUT_SERVICE,inputManager);
// 设置向WMS发起回调的callback对象
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
// 正式启动IMS
inputManager.start();
}
}
InputManagerService.java {
static class Injector {
private final Context mContext;
private final Looper mLooper;
NativeInputManagerService getNativeService(InputManagerService service) {
return new NativeInputManagerService.NativeImpl(service, mContext, mLooper.getQueue());
}
}
InputManagerService(Injector injector) {
mHandler = new InputManagerHandler(injector.getLooper());
mNative = injector.getNativeService(this);
}
public void start() {
Slog.i(TAG, "Starting input manager");
mNative.start();
}
}
NativeInputManagerService.java {
class NativeImpl implements NativeInputManagerService {
/** Pointer to native input manager service object, used by native code. */
private final long mPtr;
NativeImpl(InputManagerService service, Context context, MessageQueue messageQueue) {
mPtr = init(service, context, messageQueue);
}
private native long init(InputManagerService service, Context context,MessageQueue messageQueue);
public native void start();
}
}
InputManagerService.cpp {
static const JNINativeMethod gInputManagerMethods[] = {
{"init","(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
(void*)nativeInit},
{"start", "()V", (void*)nativeStart},
}
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
// 新建了一个 NativeInputManager 对象
// 此对象将是 Native 层组件与 Java 层 IMS 进行通信的桥梁
// 实现了 InputReaderPolicyInterface 与 InputDispatcherPolicyInterface 两个接口
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
return reinterpret_cast<jlong>(im);
}
static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
status_t result = im->getInputManager()->start();
}
static NativeInputManager* getNativeInputManager(JNIEnv* env, jobject clazz) {
return reinterpret_cast<NativeInputManager*>(env->GetLongField(clazz,
gNativeInputManagerServiceImpl.mPtr));
}
}
NativeInputManager.cpp {
NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
// 创建 Native 层的 InputManager
InputManager* im = new InputManager(this, this);
mInputManager = im;
defaultServiceManager()->addService(String16("inputflinger"), im);
}
}
InputManager.cpp {
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
// 创建 InputDispatcher
mDispatcher = createInputDispatcher(dispatcherPolicy);
//这里的 mBlocker 即封装的 mDispatcher ,mDispatcher 实现了 InputListenerInterface 接口
//通过 getListener().notifyMotion(&args) 通知 mDispatcher 处理事件
mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
// 创建 InputReader
mReader = createInputReader(readerPolicy, *mBlocker);
}
status_t InputManager::start() {
status_t result = mDispatcher->start();
result = mReader->start();
return OK;
}
}
InputReaderFactory.cpp {
std::unique_ptr<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {
// 这里会创建 EventHub ,并设置事件回调
return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);
}
}
InputDispatcherFactory.cpp {
std::unique_ptr<InputDispatcherInterface> createInputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) {
return std::make_unique<android::inputdispatcher::InputDispatcher>(policy);
}
}
InputDispatcher.cpp {
status_t InputDispatcher::start() {
// 创建供 InputDispatcher 运行的线程 InputDispatcherThread
mThread = std::make_unique<InputThread>("InputDispatcher",
[this]() { dispatchOnce(); },
[this]() { mLooper->wake(); }
);
return OK;
}
}
InputReader.cpp {
status_t InputReader::start() {
// 创建供 InputReader 运行的线程 InputReaderThread
mThread = std::make_unique<InputThread>("InputReader",
[this]() { loopOnce(); },
[this]() { mEventHub->wake(); });
return OK;
}
}
事件读取(EventHub)与加工(InputReader)
EventHub
- 避免不断地轮询这些描述符
- 不需要为每个描述符创建独立的线程进行阻塞读取,避免了资源浪费的同时又可以获得较快的响应速度。
INotify:Linux 内核所提供的一种文件系统变化通知机制。可以监控文件系统的变化,如文件新建、删除、读写等
- inotify_init() 创建一个 inotify 对象,返回一个 notifyFd。
- inotify_add_watch 将一个或多个监听添加到 inotify 对象中。
- read() 函数从 inotify 对象中读取监听事件
Epoll:监听多个描述符的可读/可写状态。等待返回时携带了可读的描述符
- epoll_create(int max_fds) 创建一个 epoll 对象的描述符,之后对 epoll 的操作均使用这个描述符完成。max_fds 参数表示了此 epoll 对象可以监听的描述符的最大数量。
- epoll_ctl (int epfd, int op,int fd, struct epoll_event *event) 用于管理注册事件的函数。这个函数可以增加/删除/修改事件的注册。
- int epoll_wait(int epfd, structepoll_event * events, int maxevents, int timeout) 用于等待事件的到来。当此函数返回时,events 数组参数中将会包含产生事件的文件描述符。
EventHub.cpp {
EventHub::EventHub(void) : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),mNextDeviceId(1),mControllerNumbers(),mNeedToSendFinishedDeviceScan(false),mNeedToReopenDevices(false),mNeedToScanDevices(true),mPendingEventCount(0),mPendingEventIndex(0),mPendingINotify(false) {
//使用epoll_create()函数创建一个epoll对象,用来监听设备节点是否有数据可读(有无事件)
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
//创建一个 inotify 对象 。这个对象将被用来 监听设备节点的增删事件
mINotifyFd = inotify_init1(IN_CLOEXEC);
std::error_code errorCode;
bool isDeviceInotifyAdded = false;
if (std::filesystem::exists("/dev/input", errorCode)) {
// 将存储设备节点的路径 /dev/input 作为监听对象添加到inotify对象中
// 当此文件夹下的设备节点发生创建与删除事件时,都可以通过mINotifyFd读取事件的详细信息
mDeviceInputWd = inotify_add_watch(mINotifyFd, "/dev/input", IN_DELETE | IN_CREATE);
}
struct epoll_event eventItem = {};
eventItem.events = EPOLLIN | EPOLLWAKEUP;
eventItem.data.fd = mINotifyFd;
// 将 mINotifyFd 作为 epoll 的一个监控对象
// 当 inotify 事件到来时,epoll_wait() 将立刻返回
// EventHub 便可从 mINotifyFd 中读取设备节点的增删信息,并作相应处理
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
}
}
InputReader
源码分析
InputReader.cpp {
status_t InputReader::start() {
mThread = std::make_unique<InputThread>("InputReader",
[this]() { loopOnce(); },
[this]() { mEventHub->wake(); });
return OK;
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
// 读取事件,没事件时会 block
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
if (count) {
processEventsLocked(mEventBuffer, count);
}
} // release lock
mQueuedListener.flush();
}
void 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;
// 处理 输入 事件
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
// 处理 新增设备 事件
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
// 处理 删除设备 事件
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
// 处理 设备扫描完成 事件
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
}
}
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count) {
auto deviceIt = mDevices.find(eventHubId);
std::shared_ptr<InputDevice>& device = deviceIt->second;
device->process(rawEvents, count);
}
}
EventHub.cpp {
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
struct input_event readBuffer[bufferSize];
RawEvent* event = buffer;
Device* device = getDeviceByFdLocked(eventItem.data.fd);
while (mPendingEventIndex < mPendingEventCount) {
// mPendingEventIndex 指定尚未处理的 epoll_event 的索引
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
Device* device = getDeviceByFdLocked(eventItem.data.fd);
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// This must be an input event
if (eventItem.events & EPOLLIN) {
// 根据设备id 读取事件到 readBuffer 中
int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
size_t count = size_t(readSize) / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
event->when = processEventTimestamp(iev);
event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
break;
}
}
// 执行 epoll_wait() 函数等待新的事件到来
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
}
// All done, return the number of events we read.
return event - buffer;
}
}
InputDevice.cpp {
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
mapper.process(rawEvent);
});
--count;
}
}
}
SingleTouchInputMapper.cpp {
void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
TouchInputMapper::process(rawEvent);
mSingleTouchMotionAccumulator.process(rawEvent);
}
}
TouchInputMapper.cpp {
void TouchInputMapper::process(const RawEvent* rawEvent) {
mCursorButtonAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
mTouchButtonAccumulator.process(rawEvent);
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
sync(rawEvent->when, rawEvent->readTime);
}
}
void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) {
// Push a new state.
mRawStatesPending.emplace_back();
RawState& next = mRawStatesPending.back();
next.clear();
next.when = when;
next.readTime = readTime;
// Sync button state.
next.buttonState = mTouchButtonAccumulator.getButtonState() | mCursorButtonAccumulator.getButtonState();
// Sync scroll
next.rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
mCursorScrollAccumulator.finishSync();
processRawTouches(false /*timeout*/);
}
void TouchInputMapper::processRawTouches(bool timeout) {
cookAndDispatch(mCurrentRawState.when, mCurrentRawState.readTime);
}
void TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t readTime) {
updateTouchSpots();
// 内部处理各个事件,不需要的会进行拦截
dispatchButtonRelease(when, readTime, policyFlags);
dispatchHoverExit(when, readTime, policyFlags);
dispatchTouches(when, readTime, policyFlags);
dispatchHoverEnterAndMove(when, readTime, policyFlags);
dispatchButtonPress(when, readTime, policyFlags);
}
void TouchInputMapper::dispatch***(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) {
dispatchMotion(...);
}
void TouchInputMapper::dispatchMotion(nsecs_t when, nsecs_t readTime, uint32_t policyFlags,uint32_t source, int32_t action, int32_t actionButton,int32_t flags, int32_t metaState, int32_t buttonState,int32_t edgeFlags, const PointerProperties* properties,const PointerCoords* coords, const uint32_t* idToIndex,BitSet32 idBits, int32_t changedId, float xPrecision,float yPrecision, nsecs_t downTime) {
NotifyMotionArgs args(getContext()->getNextId(), when, readTime, deviceId, source, displayId,
policyFlags, action, actionButton, flags, metaState, buttonState,
MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
downTime, std::move(frames));
// Listener 为 InputDispatcher 实现
getListener().notifyMotion(&args);
}
}
InputDispatcher.cpp {
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
bool needWake = false;
{
// Just enqueue a new motion event.
std::unique_ptr<MotionEntry> newEntry = std::make_unique<MotionEntry>(args->id, args->eventTime, args->deviceId,args->source, args->displayId, policyFlags,args->action, args->actionButton, args->flags,args->metaState, args->buttonState,args->classification, args->edgeFlags,args->xPrecision, args->yPrecision,args->xCursorPosition, args->yCursorPosition,args->downTime, args->pointerCount,args->pointerProperties, args->pointerCoords);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // release lock
if (needWake) {
// 唤醒 InputDispatcher 处理接收到的事件
mLooper->wake();
}
}
bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry) {
bool needWake = mInboundQueue.empty();
mInboundQueue.push_back(std::move(newEntry));
EventEntry& entry = *(mInboundQueue.back());
switch (entry.type) {
case EventEntry::Type::KEY: {
if (...) {
needWake = true;
}
break;
}
case EventEntry::Type::MOTION: {
if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(entry))) {
......
needWake = true;
}
break;
}
}
return needWake;
}
}
事件的派发
源码分析
InputDispatcher.cpp {
status_t InputDispatcher::start() {
mThread = std::make_unique<InputThread>("InputDispatcher",
[this]() { dispatchOnce(); },
[this]() { mLooper->wake(); }
);
return OK;
}
void InputDispatcher::dispatchOnce() {
{ // acquire lock
// 处理接收的消息
dispatchOnceInnerLocked(&nextWakeupTime);
// input anr 检测
const nsecs_t nextAnrCheck = processAnrsLocked();
} // release lock
// 开启下次轮训等待 weak 唤醒
mLooper->pollOnce(timeoutMillis);
}
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
// 取出从 reader 线程入队的事件
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
switch (mPendingEvent->type) {
case EventEntry::Type::KEY: {
std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::Type::MOTION: {
std::shared_ptr<MotionEntry> motionEntry = std::static_pointer_cast<MotionEntry>(mPendingEvent);
done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
break;
}
}
}
bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Identify targets.
std::vector<InputTarget> inputTargets;
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,std::shared_ptr<EventEntry> eventEntry,const std::vector<InputTarget>& inputTargets) {
for (const InputTarget& inputTarget : inputTargets) {
// Connection 对象中,有两个集合,分别是 outboundQueue 和 waitQueue。
// outboundQueue 集合中存放发送给 APP 侧的输入事件
// waitQueue 中存放发送给 APP 侧但还没收到回应的输入事件。
sp<Connection> connection = getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
}
}
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,const sp<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget) {
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,const sp<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget) {
bool wasEmpty = connection->outboundQueue.empty();
// 事件加入到Connection对象中outboundQueue集合
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,InputTarget::FLAG_DISPATCH_AS_***);
if (wasEmpty && !connection->outboundQueue.empty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,const sp<Connection>& connection) {
while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
// 取出队首事件,进行分发
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
// Publish the event.
status_t status;
const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
switch (eventEntry.type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
// Publish the key event.
status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,dispatchEntry->resolvedEventId, keyEntry.deviceId,keyEntry.source, keyEntry.displayId,std::move(hmac), dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags, keyEntry.keyCode,keyEntry.scanCode, keyEntry.metaState,keyEntry.repeatCount, keyEntry.downTime,keyEntry.eventTime);
break;
}
case EventEntry::Type::MOTION: {
const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
// Publish the motion event.
status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,dispatchEntry->resolvedEventId,motionEntry.deviceId, motionEntry.source,motionEntry.displayId, std::move(hmac),dispatchEntry->resolvedAction,motionEntry.actionButton,dispatchEntry->resolvedFlags,motionEntry.edgeFlags, motionEntry.metaState,motionEntry.buttonState,motionEntry.classification,dispatchEntry->transform,motionEntry.xPrecision, motionEntry.yPrecision,motionEntry.xCursorPosition,motionEntry.yCursorPosition,dispatchEntry->rawTransform,motionEntry.downTime, motionEntry.eventTime,motionEntry.pointerCount,motionEntry.pointerProperties, usingCoords);
break;
}
}
}
}
InputTransport.cpp {
status_t InputPublisher::publishMotionEvent(...) {
InputMessage msg;
msg.header.type = InputMessage::Type::MOTION;
msg.header.seq = seq;
msg.body.motion.eventId = eventId;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.displayId = displayId;
msg.body.motion.hmac = std::move(hmac);
msg.body.motion.action = action;
msg.body.motion.actionButton = actionButton;
msg.body.motion.flags = flags;
msg.body.motion.edgeFlags = edgeFlags;
msg.body.motion.metaState = metaState;
msg.body.motion.buttonState = buttonState;
......
return mChannel->sendMessage(&msg);
}
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
// socket 的方式发送到客户端,通过的是 FD 管道
nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
return OK;
}
}
客户端
事件接收初始化
源码分析
ViewRootImpl.java {
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
inputChannel = new InputChannel();
}
// 创建 channel
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
// 通过 loop 监听 channel 的 fd
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,Looper.myLooper());
}
}
Session.java {
public int addToDisplayAsUser(...,InputChannel outInputChannel,...) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
requestedVisibilities, outInputChannel, outInsetsState, outActiveControls,
outAttachedFrame, outSizeCompatScale);
}
}
WindowManagerService.java {
public int addWindow(...,InputChannel outInputChannel,...){
final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);
final boolean openInputChannels = (outInputChannel != null && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
}
}
WindowState.java {
void openInputChannel(InputChannel outInputChannel) {
String name = getName();
// 创建两个 channel
mInputChannel = mWmService.mInputManager.createInputChannel(name);
mInputChannelToken = mInputChannel.getToken();
mInputWindowHandle.setToken(mInputChannelToken);
mWmService.mInputToWindowMap.put(mInputChannelToken, this);
if (outInputChannel != null) {
// 将服务端创建的 InputChannel 赋值给 outInputChannel
mInputChannel.copyTo(outInputChannel);
}
}
}
InputManagerService.java {
public InputChannel createInputChannel(String name) {
return mNative.createInputChannel(name);
}
}
com_android_server_input_InputManagerService.cpp {
static jobject nativeCreateInputChannel(JNIEnv* env, jobject nativeImplObj, jstring nameObj) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
// Native 层 InputChannel 的创建
base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(name);
//Java 层 InputChannel 的创建
jobject inputChannelObj = android_view_InputChannel_createJavaObject(env, std::move(*inputChannel));
return inputChannelObj;
}
}
NativeInputManager.cpp {
base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(const std::string& name) {
return mInputManager->getDispatcher().createInputChannel(name);
}
}
InputDispatcher.cpp {
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
// 创建 客户端与服务端的 InputChannel,使用 socket 进行通信
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
{ // acquire lock
const sp<IBinder>& token = serverChannel->getConnectionToken();
// 封装 connection 用于 服务端事件分发
sp<Connection> connection = new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);
mConnectionsByToken.emplace(token, connection);
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
int fd = serverChannel->getFd();
// 服务端 接收 客户端发送的事件,代表 客户端 消息处理完成
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
} // release lock
return clientChannel;
}
}
InputTransport.cpp {
status_t InputChannel::openInputChannelPair(const std::string& name,
std::unique_ptr<InputChannel>& outServerChannel,
std::unique_ptr<InputChannel>& outClientChannel) {
int sockets[2];
int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(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));
sp<IBinder> token = new BBinder();
std::string serverChannelName = name + " (server)";
android::base::unique_fd serverFd(sockets[0]);
outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
std::string clientChannelName = name + " (client)";
android::base::unique_fd clientFd(sockets[1]);
outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
return OK;
}
}
WindowInputEventReceiver.java {
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
mInputChannel, mMessageQueue);
}
}
android_view_InputEventReceiver.cpp {
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,jobject inputChannelObj, jobject messageQueueObj) {
//根据 java 层 InputChannel 找到对应 Native 层 InputChannel
std::shared_ptr<InputChannel> inputChannel =
android_view_InputChannel_getInputChannel(env, inputChannelObj);
//根据 java 层 MessageQueue 找到对应 Native 层消息队列
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
//创建 Native 层接收器,inputChannel 交给 mInputConsumer(inputChannel)
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,receiverWeak, inputChannel, messageQueue);
status_t status = receiver->initialize();
return reinterpret_cast<jlong>(receiver.get());
}
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
//当监听的句柄 fd 发生事件,触发 NativeInputEventReceiver#handleEvent 方法
mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
}
事件接收
源码分析
android_view_InputEventReceiver.cpp {
//当监听的句柄 fd 发生事件,触发 NativeInputEventReceiver#handleEvent 方法
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
}
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
for (;;) {
InputEvent* inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,consumeBatches, frameTime, &seq, &inputEvent);
jobject inputEventObj;
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY:
inputEventObj = android_view_KeyEvent_fromNative(env,static_cast<KeyEvent*>(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION: {
MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
break;
}
}
if (inputEventObj) {
// receiverWeak 是 ViewRootImpl 中创建的 WindowInputEventReceiver 对象
// call WindowInputEventReceiver 的 dispatchInputEvent 方法
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
}
}
}
}
InputTransport.cpp {
status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
while (!*outEvent) {
// 从 socket 中读取 InputMessage
status_t result = mChannel->receiveMessage(&mMsg);
switch (mMsg.header.type) {
case InputMessage::Type::KEY: {
KeyEvent* keyEvent = factory->createKeyEvent();
// 将 InputMessage 封装成 keyEvent
initializeKeyEvent(keyEvent, &mMsg);
*outSeq = mMsg.header.seq;
*outEvent = keyEvent;
break;
}
case InputMessage::Type::MOTION: {
MotionEvent* motionEvent = factory->createMotionEvent();
updateTouchState(mMsg);
// 将 InputMessage 封装成 MotionEvent
initializeMotionEvent(motionEvent, &mMsg);
*outSeq = mMsg.header.seq;
*outEvent = motionEvent;
break;
}
}
return OK;
}
void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) {
event->initialize(msg->body.motion.eventId, msg->body.motion.deviceId, msg->body.motion.source,msg->body.motion.displayId, msg->body.motion.hmac, msg->body.motion.action,msg->body.motion.actionButton, msg->body.motion.flags,msg->body.motion.edgeFlags, msg->body.motion.metaState,
msg->body.motion.buttonState, msg->body.motion.classification, transform,msg->body.motion.xPrecision, msg->body.motion.yPrecision,msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition,displayTransform, msg->body.motion.downTime, msg->body.motion.eventTime,pointerCount, pointerProperties, pointerCoords);
}
status_t InputChannel::receiveMessage(InputMessage* msg) {
ssize_t nRead;
do {
// 通过 socket 接收 InputDispatcher 发送的数据
nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);
} while (nRead == -1 && errno == EINTR);
return OK;
}
}
事件分发
源码分析
ViewRootImpl.java {
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {
if (inputChannel != null) {
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,Looper.myLooper());
}
}
final class WindowInputEventReceiver extends InputEventReceiver {
// call by native
private void dispatchInputEvent(int seq, InputEvent event) {
onInputEvent(event);
}
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
}
void enqueueInputEvent(InputEvent event,InputEventReceiver receiver, int flags, boolean processImmediately) {
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
mPendingInputEventTail = q;
doProcessInputEvents();
}
void doProcessInputEvents() {
// Deliver all pending input events in the queue.
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
deliverInputEvent(q);
}
}
private void deliverInputEvent(QueuedInputEvent q) {
try {
InputStage stage;
stage.deliver(q);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
abstract class InputStage {
public final void deliver(QueuedInputEvent q) {
result = onProcess(q);
}
}
final class ViewPostImeInputStage extends InputStage {
protected int onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) {
return processKeyEvent(q);
} else {
return processPointerEvent(q);
}
}
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
boolean handled = mView.dispatchPointerEvent(event);
return handled ? FINISH_HANDLED : FORWARD;
}
}
}
View.java {
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}
}
DecorView.java {
public boolean dispatchTouchEvent(MotionEvent event) {
//Activity 实现了 Window.Callback 这个接口
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
}
Activity.java {
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
}
PhoneWindow.java {
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
}
DecorView.java {
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
}
ViewGroup.java {
public boolean dispatchTouchEvent(MotionEvent ev) {
onInterceptTouchEvent(ev);
for (int i = childrenCount - 1; i >= 0; i--) {
dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)
}
}
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
return child.dispatchTouchEvent(event);
}
}
View.java{
public boolean dispatchTouchEvent(MotionEvent event) {
onTouchEvent(event)
}
public boolean onTouchEvent(MotionEvent event) {
//do sameing
}
}
相关工具
getevent
adb shell getevent [-选项] [device_path]
查询 所有设备节点,event0:音量加、电源,event1:音量减
音量加减、 电源键 事件输入,SYN_REPORT 为单个事件的结束标志。
常见 EventCode
key | 描述 |
---|---|
EV_KEY | 键盘、按钮或其他类似按键的状态变化 |
EV_REL | 相对坐标轴值的变化,例如鼠标移动5个单位 |
EV_ABS | 绝对轴值的变化,例如触摸屏上触摸的坐标 |
SYN_REPORT | 将事件同步并打包 |
<事件发生时间> <事件类型> <事件代码> <事件值>
产生事件时的时间戳([ 2038.027687])
产生事件的设备节点(/dev/input/event0)
事件类型(0001),事件代码(0073)以及事件的值(00000001)
sendevent
sendevent <节点路径> <类型><代码> <值>
sendevent 的输入参数与 getevent 的输出是对应的,只不过 sendevent 的参数为十进制。
模拟音量+键:音量+ 键的代码 0x73 的十进制为 115
dumpsys input
$adb shell dumpsys input
Event Hub State:
......
10: virtual_input_device
Classes: 0x00000065
Path: /dev/input/event9
Enabled: true
Descriptor: ea011df68d5e458fae3d98067e2d851a8bb4cac2
Location:
ControllerNumber: 6
UniqueId:
Identifier: bus=0x0006, vendor=0x1234, product=0x5678, version=0x0001
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
Input Reader State:
......
Device 10: virtual_input_device
Input Dispatcher State:
......
Display: 5
Windows:
Display: 0
相关文档
触摸设备 | Android 开源项目 | Android Open Source Project
Linux 输入事件代码
Linux 多点触控协议
Linux 输入驱动程序