Android 11.0源码系列之IMSInputDispatcher
Posted bubbleben
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 11.0源码系列之IMSInputDispatcher相关的知识,希望对你有一定的参考价值。
本篇涉及到的主要代码:
\\system\\core\\libutils\\Looper.cpp
\\frameworks\\native\\libs\\input\\InputTransport.cpp
\\frameworks\\native\\services\\inputflinger\\dispatcher\\InputDispatcher.h
\\frameworks\\native\\services\\inputflinger\\reader\\InputThread.cpp
\\frameworks\\native\\services\\inputflinger\\reader\\InputDispatcher.cpp
上一篇我们介绍了libinputflinger.so
中InputManager
的创建:它在创建过程中启动了非常重要的两个对象InputReader
和InputDispatcher
,它们分别用于读取input事件和分发input事件,本篇将先介绍InputDispatcher
的工作流程。
1.1 InputDispatcher的构造函数
[-> InputDispatcher.cpp]
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
// NativeInputManager
: mPolicy(policy),
// EventEntry类型的待处理的输入事件,初始化为空
mPendingEvent(nullptr),
// 焦点display id,默认为0即main display
mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
// 创建native层Looper[见1.11小节]
mLooper = new Looper(false);
// 调用InputManagerService.getKeyRepeatTimeout获取长按超时时间,默认为400ms
// 调用InputManagerService.getKeyRepeatDelay获取长按延时时间,默认为50ms
policy->getDispatcherConfiguration(&mConfig);
}
在InputDispatcher
的构造函数中:将InputDispatcherPolicyInterface
类型的policy
赋值给mPolicy
,在上一篇文章中我们介绍过JNI层的NativeInputManager
同时继承了InputDispatcherPolicyInterface
和InputReaderPolicyInterface
,所以InputDispatcher
就可以通过mPolicy
回调NativeInputManager
进而调用Java层InputManagerService
的方法来完成诸如拦截按键/触摸消息,通知焦点改变,通知ANR等工作,同时创建了native层的Looper
,初始化参数allowNonCallbacks
为false,接下来我们看看这里的Looper
于Java层的Looper
有什么区别?
1.11 Looper的创建
[-> /system/core/libutils/Looper.cpp]
Looper::Looper(bool allowNonCallbacks)
// 传入的allowNonCallbacks为false
: mAllowNonCallbacks(allowNonCallbacks),
mSendingMessage(false),
mPolling(false),
mEpollRebuildRequired(false),
mNextRequestSeq(0),
mResponseIndex(0),
mNextMessageUptime(LLONG_MAX) {
// 重置mWakeEventFd
mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
AutoMutex _l(mLock);
// 重建epoll[见1.12小节]
rebuildEpollLocked();
}
1.12 epoll实例的创建
void Looper::rebuildEpollLocked() {
// Allocate the new epoll instance and register the wake pipe.
// 创建epoll实例并将其文件描述符赋值给mEpollFd
mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeEventFd.get();
// 将mWakeEventFd发送给epoll实例,用于唤醒InputDispatcher对应的线程
int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &eventItem);
for (size_t i = 0; i < mRequests.size(); i++) {
const Request& request = mRequests.valueAt(i);
struct epoll_event eventItem;
request.initEventItem(&eventItem);
// 将Request发送给epoll实例,用于,这里的mRequests是在何时添加的呢?[见1.13小节]
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",
request.fd, strerror(errno));
}
}
}
1.13 Request的创建
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
// addFd是何时被调用的呢?[见1.14小节]
if (!callback.get()) {
if (! mAllowNonCallbacks) {
// 创建Looper时如果传入的allowNonCallbacks为false,则必须传入callback,否则直接返回
ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
return -1;
}
}
{ // acquire lock
AutoMutex _l(mLock);
// 创建Request
Request request;
request.fd = fd;
request.ident = ident;
request.events = events;
request.seq = mNextRequestSeq++;
request.callback = callback;
request.data = data;
if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
struct epoll_event eventItem;
// 构建epoll_event
request.initEventItem(&eventItem);
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex < 0) {
// 之前未添加过,则直接添加
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
mRequests.add(fd, request);
} else {
// 否则先修改后再替换
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_MOD, fd, &eventItem);
if (epollResult < 0) {
if (errno == ENOENT) {
epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
scheduleEpollRebuildLocked();
}
}
mRequests.replaceValueAt(requestIndex, request);
}
} // release lock
return 1;
}
1.14 Looper.addFd的调用
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
{ // acquire lock
std::scoped_lock _l(mLock);
// 获取InputChannel对应的Connection
sp<Connection> existingConnection = getConnectionLocked(inputChannel->getConnectionToken());
// 如果之前已经注册过该InputChannel则直接返回
if (existingConnection != nullptr) {
ALOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().c_str());
return BAD_VALUE;
}
// 创建InputChannel对应的Connection
sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator);
// 获取InputChannel对应的文件描述符
int fd = inputChannel->getFd();
mConnectionsByFd[fd] = connection;
mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel;
// 调用Looper.addFd监听InputChannel的读操作
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
} // release lock
// Wake the looper because some connections have changed.
// 唤醒InputDispatcher对应的线程
mLooper->wake();
return OK;
}
这里的Lopper(system/core/libutils/Looper.cpp
)并非我们Java层常用的``Looper(frameworks/base/core/java/android/os)
,它基于epoll
机制实现主要用于文件描述符的监听,由于epoll
并非本文的重点所以我们目前只需要简单了解即可;
1.2 InputDispatcher线程的启动
[-> InputDispatcher.cpp]
status_t InputDispatcher::start() {
// 如果线程已经启动则直接返回
if (mThread) {
return ALREADY_EXISTS;
}
// 否则创建InputThread,传入loop和wake方法
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
[-> InputThread.cpp]
// Implementation of Thread from libutils.
class InputThreadImpl : public Thread {
public:
explicit InputThreadImpl(std::function<void()> loop)
: Thread(/* canCallJava */ true), mThreadLoop(loop) {}
~InputThreadImpl() {}
private:
std::function<void()> mThreadLoop;
bool threadLoop() override {
// dispatchOnce[见1.3小节]
mThreadLoop();
return true;
}
};
} // namespace
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
: mName(name), mThreadWake(wake) {
mThread = new InputThreadImpl(loop);
mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}
InputThread
只是对InputThreadImpl
的封装,InputThreadImpl
才是一个真正的线程,我们传入了三个参数:线程名–“InputDispatcher”,loop函数–dispatchOnce()
,wake函数–Looper.wake()
,在调用InputThreadImpl.run
方法之后,线程就开始运行起来并调用threadLoop
方法开始消息队列的循环处理,这样也就回到了dispatchOnce()
方法;
1.3 InputDispatcher的消息循环
[-> InputDispatcher.cpp]
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
// 如果mCommandQueue没有待处理的Command,则执行dispatchOnceInnerLocked去产生Command[见1.4小节]
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
// 如果mCommandQueue队列消息不为空,则循环从中取出Command进行处理
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
// If we are still waiting for ack on some events,
// we might have to wake up earlier to check if an app is anr'ing.
// 判断是否要触发ANR
const nsecs_t nextAnrCheck = processAnrsLocked();
// 下一次唤醒时间
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
} // release lock
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
// 等待epoll的响应
mLooper->pollOnce(timeoutMillis);
}
dispatchOnce()
会根据mCommandQueue
队列里是否有未执行的Command
来判断是否执行dispatchOnceInnerLocked
,如果有的话则循环从中取出CommandEntry
并执行其command
方法,这里CommandEntry
的来源除了事件分发以外,还有焦点改变,配置改变以及触发ANR等事件,最后根据消息的超时情况来判断是否需要触发ANR;在开启接下来的流程之前,我们先记下几个比较重要的数据结构和队列,它们都由同一把锁保护,以后我们会频繁的与它们打交道,这其中最重要的及时mInboundQueue
,它保存的是即将发送给InputChannel
去处理的输入事件,而其来源则是InputReader
,我们会在接下来关于InputReader
的文章中作更详细的介绍;
// 待处理的输入事件
EventEntry* mPendingEvent GUARDED_BY(mLock);
// Blocked event latency optimization. Drops old events when the user intends
// to transfer focus to a new application.
// 下一个未阻塞的输入事件
EventEntry* mNextUnblockedEvent GUARDED_BY(mLock);
// mInboundQueue输入事件队列
std::deque<EventEntry*> mInboundQueue GUARDED_BY(mLock);
// mRecentQueue输入事件队列
std::deque<EventEntry*> mRecentQueue GUARDED_BY(mLock);
// mCommandQueue命令队列
std::deque<std::unique_ptr<CommandEntry>> mCommandQueue GUARDED_BY(mLock);
1.4 分类处理输入事件
[-> InputDispatcher.cpp]
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
// 记录当前时间
nsecs_t currentTime = now();
// Ready to start a new event.
// If we don't already have a pending event, go grab one.
// mPendingEvent初始化为空
if (!mPendingEvent) {
if (mInboundQueue.empty()) {
......
// 如果mInboundQueue队列为空,而且没有待处理的输入事件则直接返回
// Nothing to do if there is no pending event.
if (!mPendingEvent) {
return;
}
} else {
// 否则直接从mInboundQueue队列头取出一个EventEntry来处理
// Inbound queue has at least one entry.
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(*mPendingEvent);
}
}
......
switch (mPendingEvent->type) {
......
case EventEntry::Type::MOTION: {
// 将mPendingEvent强转为MotionEntry
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
dropReason = DropReason::APP_SWITCH;
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry)) {
dropReason = DropReason::STALE;
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DropReason::BLOCKED;
}
// 如果是Motion Event则会走dispatchMotionLocked分支[见1.5小节]
done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
}
if (done) {
if (dropReason != DropReason::NOT_DROPPED) {
dropInboundEventLocked(*mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
// 处理完成之后释放mPendingEvent
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
dispatchOnceInnerLocked
会从mInboundQueue
队头取出EntryEvent
赋值给mPendingEvent
,并根据输入事件的类型作不同的处理,处理完成之后再释放mPendingEvent
,这里我们以MotionEvent
为例来分析输入事件的处理流程;
1.5 处理触摸事件
[-> InputDispatcher.cpp]
bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// 判断是否是Touch事件
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
// Identify targets.
std::vector<InputTarget> inputTargets;
if (isPointerEvent) {
// Pointer event. (eg. touchscreen)
// 寻找Touch事件的焦点窗口
injectionResult =
findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
&conflictingPointerActions);
} else {
// Non touch event. (eg. trackball)
// 寻找非Touch事件的焦点窗口[见1.6小节]
injectionResult =
findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
}
// 对于MotionEvent有3种情况会返回INPUT_EVENT_INJECTION_PENDING状态
// 焦点窗口为空而焦点应用不为空时分两种情况:
// 1.未设置焦点窗口缺失的超时时间;
// 2.焦点窗口缺少的超时时间还未到;
// 焦点窗口和焦点应用都不为空时:
// 3.焦点窗口处于暂停状态;
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResult(entry, injectionResult);
if (injectionResult == INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
ALOGW("Permission denied, dropping the motion (isPointer=%s)", toString(isPointerEvent));
return true;
}
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
CancelationOptions::Mode mode(isPointerEvent
? CancelationOptions::CANCEL_POINTER_EVENTS
: CancelationOptions::CANCEL_NON_POINTER_EVENTS);
CancelationOptions options(mode, "input event injection failed");
synthesizeCancelationEventsForMonitorsLocked(options);
return true;
}
// 找到目标窗口之后开始分发事件[见1.9小节]
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
针对Touch事件和非Touch事件,有两种不同的逻辑来寻找焦点窗口:findTouchedWindowTargetsLocked
中有很多关于分屏和多display id的处理逻辑,相比findFocusedWindowTargetsLocked
而言代码逻辑稍显复杂,为了聚焦事件分发的主线流程,我们以findFocusedWindowTargetsLocked
为例来说明焦点窗口的寻找过程;
1.6 寻找焦点窗口
[-> InputDispatcher.cpp]
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry& entry,
std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime) {
std::string reason;
// 寻找输入事件的display id,由于Android支持多屏设备,所以可能会有多个display id,默认为0
int32_t displayId = getTargetDisplayId(entry);
// 根据display id查找InputWindowHandle
sp<InputWindowHandle> focusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
// 根据display id查找InputApplicationHandle
sp<InputApplicationHandle> focusedApplicationHandle =
getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
// If there is no currently focused window and no focused application
// then drop the event.
// 如果focusedWindowHandle和focusedApplicationHandle同时为空,代表当前即无焦点应用也无焦点窗口,所以直接将此事件丢弃
if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
ALOGI("Dropping %s event because there is no focused window or focused application in "
"display %" PRId32 ".",
EventEntry::typeToString(entry.type), displayId);
return INPUT_EVENT_INJECTION_FAILED;
}
// Compatibility behavior: raise ANR if there is a focused application, but no focused window.
// Only start counting when we have a focused event to dispatch. The ANR is canceled if we
// start interacting with another application via touch (app switch). This code can be removed
// if the "no focused window ANR" is moved to the policy. Input doesn't know whether
// an app is expected to have a focused window.
// 焦点应用不为空而焦点窗口为空
if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
// 未设置焦点窗口缺失的超时时间
if (!mNoFocusedWindowTimeoutTime.has_value()) {
// We just discovered that there's no focused window. Start the ANR timer
// 获取超时时间,默认为5s
const nsecs_t timeout = focusedApplicationHandle->getDispatchingTimeout(
DEFAULT_INPUT_DISPATCHING_TIMEOUT.count());
// 记录超时时间
mNoFocusedWindowTimeoutTime = currentTime + timeout;
// 记录等待焦点窗口的焦点应用
mAwaitedFocusedApplication = focusedApplicationHandle;
ALOGW("Waiting because no window has focus but %s may eventually add a "
"window when it finishes starting up. Will wait for %" PRId64 "ms",
mAwaitedFocusedApplication->getName().c_str(), ns2ms(timeout));
*nextWakeupTime = *mNoFocusedWindowTimeoutTime;
return INPUT_EVENT_INJECTION_PENDING;
} else if (currentTime > *mNoFocusedWindowTimeoutTime) {
// Already raised ANR. Drop the event
// 如果已经超时,则直接丢弃该事件
ALOGE("Dropping %s event because there is no focused window",
EventEntry::typeToString(entry.type));
return INPUT_EVENT_INJECTION_FAILED;
} else {
// Still waiting for the focused window
// 还未到超时时间则继续等待
return INPUT_EVENT_INJECTION_PENDING;
}
}
// we have a valid, non-null focused window
// 重置超时时间和等待的焦点应用
resetNoFocusedWindowTimeoutLocked();
// Check permissions.
if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
return INPUT_EVENT_INJECTION_PERMISSION_DENIED;
}
// 焦点窗口已经paused
if (focusedWindowHandle->getInfo()->paused) {
ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
return INPUT_EVENT_INJECTION_PENDING;
}
// Success! Output targets.
// 成功找到焦点窗口后,将其添加到inputTargets[见1.9小节]
addWindowTargetLocked(focusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
BitSet32(0), inputTargets);
// Done.
return INPUT_EVENT_INJECTION_SUCCEEDED;
}
这里有两个非常重要的map:mFocusedWindowHandlesByDisplay
和mFocusedApplicationHandlesByDisplay
,它们分别存储着当前每个display对应的焦点应用和焦点窗口;
[-> InputDispatcher.h]
// Focus tracking for keys, trackball, etc.
// key为display id,value为InputWindowHandle即焦点窗口,更新过程见[1.7小节]
std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
GUARDED_BY(mLock);
// key为display id,value为InputApplicationHandle即焦点应用,更新过程见[1.8小节]
// Focused applications.
std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
GUARDED_BY(mLock);
1.7 设置焦点窗口
[-> InputDispatcher.cpp]
void InputDispatcher::setInputWindowsLocked(
const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
......
// Copy old handles for release if they are no longer present.
// 根据displayId从mWindowHandlesByDisplay中查找出当前所有的InputWindowHandle,包括焦点窗口和非焦点窗口
const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
// 根据传入的窗口列表inputWindowHandles来更新mWindowHandlesByDisplay
updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId);
sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
bool foundHoveredWindow = false;
for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
// Set newFocusedWindowHandle to the top most focused window instead of the last one
// 遍历更新之后的所有窗口列表,并将可见并且获得焦点的窗口置为新的焦点窗口
if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
windowHandle->getInfo()->visible) {
newFocusedWindowHandle = windowHandle;
}
if (windowHandle == mLastHoverWindowHandle) {
foundHoveredWindow = true;
}
}
if (!foundHoveredWindow) {
mLastHoverWindowHandle = nullptr;
}
// 根据displayId从mFocusedWindowHandlesByDisplay中查找出当前的焦点窗口
sp<InputWindowHandle> oldFocusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
// 不同的InputWindowHandle有不同的token
if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) {
if (oldFocusedWindowHandle != nullptr) {
if (DEBUG_FOCUS) {
ALOGD("Focus left window: %s in display %" PRId32,
oldFocusedWindowHandle->getName().c_str(), displayId);
}
// 根据InputWindowHandle中的Token获取到对应的额InputChannel
sp<InputChannel> focusedInputChannel =
getInputChannelLocked(oldFocusedWindowHandle->getToken());
if (focusedInputChannel != nullptr) {
CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
"focus left window");
synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
// 往mInboundQueue里添加失去焦点的FocusEntry
enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/);
}
// 从mFocusedWindowHandlesByDisplay中移除历史的InputWindowHandle
mFocusedWindowHandlesByDisplay.erase(displayId);
}
if (newFocusedWindowHandle != nullptr) {
if (DEBUG_FOCUS) {
ALOGD("Focus entered window: %s in display %" PRId32,
newFocusedWindowHandle->getName().c_str(), displayId);
}
// 更新mFocusedWindowHandlesByDisplay
mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
// 往mInboundQueue里添加得到焦点的FocusEntry
enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/);
}
// 往mCommandQueue里添加焦点改变的CommandEntry,通知上层焦点窗口改变
if (mFocusedDisplayId == displayId) {
onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
}
}
}
每个display都对应若干个InputWindowHandle
和一个焦点InputWindowHandle
,此方法会根据传入的InputWindowHandle
列表来更新mWindowHandlesByDisplay
和mFocusedWindowHandlesByDisplay
,调用流程如下所示:可以看出整个过程由SurfaceFlinger
触发;
-->frameworks/native/services/surfaceflinger/SurfaceFlinger.onMessageInvalidate
-->frameworks/native/services/surfaceflinger/SurfaceFlinger.updateInputFlinger
-->frameworks/native/services/surfaceflinger/SurfaceFlinger.updateInputWindowInfo
-->frameworks/native/services/inputflinger/IInputFlinger.setInputWindows
-->frameworks/native/services/inputflinger/InputManager.setInputWindows
-->frameworks/native/services/inputflinger/InputDispatcher.setInputWindows
-->frameworks/native/services/inputflinger/InputDispatcher.setInputWindowsLocked
1.8 设置焦点应用
[-> InputDispatcher.cpp]
void InputDispatcher::setFocusedApplication(
int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
{ // acquire lock
std::scoped_lock _l(mLock);
// 根据displayId获取历史焦点应用
sp<InputApplicationHandle> oldFocusedApplicationHandle =
getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
// 如果已经切换到新的应用,而且历史应用之前在等待焦点窗口,那么继续等待已经没有意义,所以重置等待的焦点应用和等待时间
if (oldFocusedApplicationHandle == mAwaitedFocusedApplication &&
inputApplicationHandle != oldFocusedApplicationHandle) {
resetNoFocusedWindowTimeoutLocked();
}
if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
if (oldFocusedApplicationHandle != inputApplicationHandle) {
// 更新焦点应用
mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
}
} else if (oldFocusedApplicationHandle != nullptr) {
oldFocusedApplicationHandle.clear();
// 清除历史焦点应用
mFocusedApplicationHandlesByDisplay.erase(displayId);
}
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
// 唤醒InputDispatcher线程
mLooper->wake();
}
这里会根据传入的InputApplicationHandle
来更新焦点应用,由于有多个分支会调用到这里,所以仅只列出最典型的一个,即在切换应用并且新应用Acitivity.onResume
时调用:
-->frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.setResumedActivityUncheckLocked
-->frameworks/base/services/core/java/com/android/server/wm/DisplayContent.setFocusedApp
-->frameworks/base/services/core/java/com/android/server/wm/InputMonitor.setFocusedAppLw
-->frameworks/base/services/core/java/com/android/server/input/InputManagerService.setFocusedApplication
-->frameworks/base/services/core/jni/com_android_server_input_InputManagerService.nativeSetFocusedApplication
-->frameworks/base/services/core/jni/com_android_server_input_InputManagerService.NativeInputManager.setFocusedApplication
-->frameworks/native/services/inputflinger/InputDispatcher.setFocusedApplication
1.9 添加窗口目标
[-> InputDispatcher.cpp]
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds,
std::vector<InputTarget>& inputTargets) {
// 查找windowHandle对应的InputTarget是否添加过
std::vector<InputTarget>::iterator it =
std::find_if(inputTargets.begin(), inputTargets.end(),
[&windowHandle](const InputTarget& inputTarget) {
return inputTarget.inputChannel->getConnectionToken() ==
windowHandle->getToken();
});
// 获取InputWindowHandle对应的InputWindowInfo
const InputWindowInfo* windowInfo = windowHandle->getInfo();
// 如果没有添加过则重新创建一个InputTarget
if (it == inputTargets.end()) {
InputTarget inputTarget;
// 查找InputChannel[见1.9.1小节]
sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
inputTarget.inputChannel = inputChannel;
inputTarget.flags = targetFlags;
inputTarget.globalScaleFactor = windowInfo->globalScaleFactor;
// 构造InputTarget并将其压入inputTargets中
inputTargets.push_back(inputTarget);
it = inputTargets.end() - 1;
}
it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop,
windowInfo->windowXScale, windowInfo->windowYScale);
}
1.9.1 查找InputChannel
[-> InputDispatcher.cpp]
sp<InputChannel> InputDispatcher::getInputChannelLocked(const sp<IBinder>& token) const {
// mInputChannelsByToken是在registerInputChannel或者registerInputMonitor时写入的
size_t count = mInputChannelsByToken.count(token);
if (count == 0) {
return nullptr;
}
return mInputChannelsByToken.at(token);
}
1.10 传递输入事件
[-> InputDispatcher.cpp]
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
const std::vector<InputTarget>& inputTargets) {
for (const InputTarget& inputTarget : inputTargets) {
// 找到InputChannel对应的Connection[见1.10.1小节]
sp<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
// 如果Connection不为空,则开始准备分发输入事件[见1.11小节]
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
}
}
}
根据InputTarget
查找到对应的Connection
,它是连接native的应用进程的通道,有了它就可以开始准备分发输入事件了;
1.10.1 获取Connection
[-> InputDispatcher.cpp]
sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const {
if (inputConnectionToken == nullptr) {
return nullptr;
}
// 从mConnectionsByFd中找到与InputChannel token一致的Connection
for (const auto& pair : mConnectionsByFd) {
const sp<Connection>& connection = pair.second;
if (connection->inputChannel->getConnectionToken() == inputConnectionToken) {
return connection;
}
}
return nullptr;
}
这里的mConnectionsByFd
和1.9.1小节中的mInputChannelsByToken
都是在registerInputChannel
或者registerInputMonitor
时更新的,Connection
会持有对InputChannel
的引用,所以可以根据InputChannel.getConnectionToken()
找到对应的Connection
,我们会在下一篇中详细介绍InputChannel
和Connection
的创建;
1.11 准备分发输入事件
[-> InputDispatcher.cpp]
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget) {
// Skip this event if the connection status is not normal.
// We don't want to enqueue additional outbound events if the connection is broken.
// 如果Connection状态不正常,则直接返回不会把输入事件添加到mOutbound队列
if (connection->status != Connection::STATUS_NORMAL) {
return;
}
// Not splitting. Enqueue dispatch entries for the event as is.
// 入队输入事件[见1.12小节]
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
1.12 入队输入事件
[-> InputDispatcher.cpp]
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget) {
// 判断Connection的outboundQueue是否为空
bool wasEmpty = connection->outboundQueue.empty();
// Enqueue dispatch entries for the requested modes.
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
// 入队输入事件[见1.12.1小节]
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.empty()) {
// 如果之前outboundQueue为空,经过enqueueDispatchEntryLocked之后不为空,则开始处理输入事件[见1.13小节]
startDispatchCycleLocked(currentTime, connection);
}
}
1.12.1 入队输入事件
[-> InputDispatcher.cpp]
void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget,
int32_t dispatchMode) {
......
// This is a new event.
// Enqueue a new dispatch entry onto the outbound queue for this connection.
// 将EventEntry封装为DispatchEntry
std::unique_ptr<DispatchEntry> dispatchEntry =
createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
......
// Enqueue the dispatch entry.
// 将DispatchEntry添加到Connection中的outboundQueue队列中,此时outboundQueue不为空
connection->outboundQueue.push_back(dispatchEntry.release());
traceOutboundQueueLength(connection);
}
1.13 开始分发输入事件
[-> InputDispatcher.cpp]
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
// 经过enqueueDispatchEntryLocked之后,connection->outboundQueue不为空
while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
// 记录事件分发的时间
dispatchEntry->deliveryTime = currentTime;
// 默认超时时间为5s
const nsecs_t timeout =
getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
// 分发超时时间为当前时间加上默认超时时间
dispatchEntry->timeoutTime = currentTime + timeout;
// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::Type::MOTION: {
MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
// 获取事件签名
std::array<uint8_t, 32> hmac = getSignature(*motionEntry, *dispatchEntry);
// Publish the motion event.
// 通过Connection的InputPublisher.publishMotionEvent将输入事件发布出去[见1.14小节]
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, xScale, yScale,
xOffset, yOffset, motionEntry->xPrecision,
motionEntry->yPrecision,
motionEntry->xCursorPosition,
motionEntry->yCursorPosition,
motionEntry->downTime, motionEntry->eventTime,
motionEntry->pointerCount,
motionEntry->pointerProperties, usingCoords);
reportTouchEventForStatistics(*motionEntry);
break;
}
}
// Re-enqueue the event on the wait queue.
// 发布完之后将DispatchEntry从Connection的outboundQueue中移除
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
// 然后将DispatchEntry加入Connection的waitQueue
connection->waitQueue.push_back(dispatchEntry);
if (connection->responsive) {
// 往AnrTracker中插入一条记录
mAnrTracker.insert(dispatchEntry->timeoutTime,
connection->inputChannel->getConnectionToken());
}
traceWaitQueueLength(connection);
}
}
1.14 发布输入事件
[-> InputTransport.cpp]
status_t InputPublisher::publishMotionEvent(
uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
int32_t edgeFlags, int32_t metaState, int32_t buttonState,
MotionClassification classification, float xScale, float yScale, float xOffset,
float yOffset, float xPrecision, float yPrecision, float xCursorPosition,
float yCursorPosition, nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
InputMessage msg;
msg.header.type = InputMessage::Type::MOTION;
msg.body.motion.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;
msg.body.motion.classification = classification;
msg.body.motion.xScale = xScale;
msg.body.motion.yScale = yScale;
msg.body.motion.xOffset = xOffset;
msg.body.motion.yOffset = yOffset;
msg.body.motion.xPrecision = xPrecision;
msg.body.motion.yPrecision = yPrecision;
msg.body.motion.xCursorPosition = xCursorPosition;
msg.body.motion.yCursorPosition = yCursorPosition;
msg.body.motion.downTime = downTime;
msg.body.motion.eventTime = eventTime;
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]);
}
// 将输入事件封装成InputMessage,并继续通过InputChannel.sendMessage发送消息[见1.15小节]
return mChannel->sendMessage(&msg);
}
1.15 发送输入事件给应用进程
[-> InputTransport.cpp]
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
// 通过socket将InputMessage发送给应用进程
nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
......
return OK;
}
至此InputDispatcher
的工作算是告一段落,兜兜转转最终通过socket将输入事件发送给客户端,但是我们的客户端是谁?socket是什么时候创建的?InputChannel
,Connection
,mFd
,Token
这些类分别代表什么含义,我们目前还不得而知,受制于篇幅的限制这些疑问我们会留到下一篇文章来解答。
以上是关于Android 11.0源码系列之IMSInputDispatcher的主要内容,如果未能解决你的问题,请参考以下文章
Android 11.0源码系列之IMSInputManagerService
Android 11.0源码系列之IMSInputManager
Android 11.0源码系列之IMSInputDispatcher