概述
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();}@Overridepublic 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());// 正式启动IMSinputManager.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 层的 InputManagerInputManager* im = new InputManager(this, this);mInputManager = im;defaultServiceManager()->addService(String16("inputflinger"), im);}
}
InputManager.cpp {InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {// 创建 InputDispatchermDispatcher = createInputDispatcher(dispatcherPolicy);//这里的 mBlocker 即封装的 mDispatcher ,mDispatcher 实现了 InputListenerInterface 接口//通过 getListener().notifyMotion(&args) 通知 mDispatcher 处理事件mClassifier = std::make_unique<InputClassifier>(*mDispatcher);mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);// 创建 InputReadermReader = 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 运行的线程 InputDispatcherThreadmThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });return OK;}
}
InputReader.cpp {status_t InputReader::start() {// 创建供 InputReader 运行的线程 InputReaderThreadmThread = 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;// 读取事件,没事件时会 blocksize_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lockif (count) {processEventsLocked(mEventBuffer, count);}} // release lockmQueuedListener.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 happenbreak;}}}}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 eventif (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 scrollnext.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 lockif (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();}// 创建 channelres = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mDisplayCutout, inputChannel,mTempInsets, mTempControls);// 通过 loop 监听 channel 的 fdmInputEventReceiver = 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();// 创建两个 channelmInputChannel = mWmService.mInputManager.createInputChannel(name);mInputChannelToken = mInputChannel.getToken();mInputWindowHandle.setToken(mInputChannelToken);mWmService.mInputToWindowMap.put(mInputChannelToken, this);if (outInputChannel != null) {// 将服务端创建的 InputChannel 赋值给 outInputChannelmInputChannel.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 lockconst 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 lockreturn 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 层 InputChannelstd::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 中读取 InputMessagestatus_t result = mChannel->receiveMessage(&mMsg);switch (mMsg.header.type) {case InputMessage::Type::KEY: {KeyEvent* keyEvent = factory->createKeyEvent();// 将 InputMessage 封装成 keyEventinitializeKeyEvent(keyEvent, &mMsg);*outSeq = mMsg.header.seq;*outEvent = keyEvent;break;}case InputMessage::Type::MOTION: {MotionEvent* motionEvent = factory->createMotionEvent();updateTouchState(mMsg);// 将 InputMessage 封装成 MotionEventinitializeMotionEvent(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 nativeprivate void dispatchInputEvent(int seq, InputEvent event) {onInputEvent(event);}@Overridepublic 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_deviceClasses: 0x00000065Path: /dev/input/event9Enabled: trueDescriptor: ea011df68d5e458fae3d98067e2d851a8bb4cac2Location:ControllerNumber: 6UniqueId:Identifier: bus=0x0006, vendor=0x1234, product=0x5678, version=0x0001KeyLayoutFile: /system/usr/keylayout/Generic.klKeyCharacterMapFile: /system/usr/keychars/Generic.kcmConfigurationFile:HaveKeyboardLayoutOverlay: falseVideoDevice: <none>
Input Reader State:......Device 10: virtual_input_device
Input Dispatcher State:......Display: 5Windows:Display: 0
相关文档
触摸设备 | Android 开源项目 | Android Open Source Project
Linux 输入事件代码
Linux 多点触控协议
Linux 输入驱动程序