最后看一下学习需要的所有知识点的思维导图。在刚刚那份学习笔记里包含了下面知识点所有内容!文章里已经展示了部分!如果你正愁这块不知道如何学习或者想提升学习这块知识的学习效率,那么这份学习笔记绝对是你的秘密武器!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
// 焦点应用不为空而焦点窗口为空
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) {
// 如果已经超时,则直接丢弃该事件
ALOGE("Dropping %s event because there is no focused window",
EventEntry::typeToString(entry.type));
return INPUT_EVENT_INJECTION_FAILED;
} else {
// 还未到超时时间则继续等待
return INPUT_EVENT_INJECTION_PENDING;
}
}
// 重置超时时间和等待的焦点应用
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;
}
// 成功找到焦点窗口后,将其添加到inputTargets
addWindowTargetLocked(focusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
BitSet32(0), inputTargets);
// Done.
return INPUT_EVENT_INJECTION_SUCCEEDED;
}
这里有两个非常重要的map:`mFocusedWindowHandlesByDisplay`和`mFocusedApplicationHandlesByDisplay`,它们分别存储着当前每个`display`对应的焦点应用和焦点窗口,这些map在`frameworks/native/services/inputflinger/dispatcher/InputDispatcher.h`被声明:
// key为display id,value为InputWindowHandle即焦点窗口
std::unordered_map<int32_t, sp> mFocusedWindowHandlesByDisplay
GUARDED_BY(mLock);
// key为display id,value为InputApplicationHandle即焦点应用
std::unordered_map<int32_t, sp> mFocusedApplicationHandlesByDisplay
GUARDED_BY(mLock);
### 1.4 setInputWindowsLocked
`setInputWindowsLocked`用于设置焦点窗口,相关代码位于`frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp`:
void InputDispatcher::setInputWindowsLocked(
const std::vector<sp>& inputWindowHandles, int32_t displayId) {
…
// 根据displayId从mWindowHandlesByDisplay中查找出当前所有的InputWindowHandle,包括焦点窗口和非焦点窗口
const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(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`,调用流程如下所示:
–>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.5 setFocusedApplication
`setFocusedApplication`用于设置焦点应用,相关代码位于`frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp`:
void InputDispatcher::setFocusedApplication(
int32_t displayId, const std::shared_ptr& inputApplicationHandle) {
if (DEBUG_FOCUS) {
ALOGD(“setFocusedApplication displayId=%” PRId32 " %s", displayId,
inputApplicationHandle ? inputApplicationHandle->getName().c_str() : “”);
}
{ // acquire lock
std::scoped_lock _l(mLock);
// 设置焦点应用
setFocusedApplicationLocked(displayId, inputApplicationHandle);
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
}
### 1.6 dispatchEventLocked
`dispatchEventLocked`用于传递输入事件,相关代码位于`frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp`:
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
const std::vector& inputTargets) {
…
for (const InputTarget& inputTarget : inputTargets) {
// 找到InputChannel对应的Connection
sp<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
// 如果Connection不为空,则开始准备分发输入事件
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
}
}
}
`ispatchEventLocked`函数根据`InputTarget`查找到对应的`Connection`,它是连接`native`的应用进程的通道,有了它就可以开始准备分发输入事件了。
### 1.7 prepareDispatchCycleLocked
`prepareDispatchCycleLocked`函数用于准备分发输入事件,在这个函数中,将校验连接状态,当连接状态正常时,将入队输入事件,相关代码位于`frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp`:
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget) {
// 如果Connection状态不正常,则直接返回不会把输入事件添加到mOutbound队列
if (connection->status != Connection::STATUS_NORMAL) {
return;
}
…
// 入队输入事件
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
### 1.8 enqueueDispatchEntriesLocked
`enqueueDispatchEntriesLocked`函数用于入队输入事件,相关代码位于`frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp`:
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget) {
…
// 判断Connection的outboundQueue是否为空
bool wasEmpty = connection->outboundQueue.empty();
// 入队输入事件
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);
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之后不为空,则开始分发事件
startDispatchCycleLocked(currentTime, connection);
}
}
### 1.9 startDispatchCycleLocked
`startDispatchCycleLocked`用于分发输入事件,相关代码位于`frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp`:
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp& 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);
// 通过Connection的InputPublisher.publishMotionEvent将输入事件发布
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;
}
...
}
// 发布完之后将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.10 publishMotionEvent
`publishMotionEvent`函数将事件发布出去,相关代码位于`frameworks/native/libs/input/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发送消息
return mChannel->sendMessage(&msg);
}
### 1.11 sendMessage
`sendMessage`将事件发送到应用进程,相关代码位于`frameworks/native/libs/input/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`发送给客户端,下面给出inputDispatcher的整体流程图供大家餐参考:
![](https://img-blog.csdnimg.cn/d0259254932540e59a4a742ba12e2b93.png)
最后,如果大伙有什么好的学习方法或建议欢迎大家在评论中积极留言哈,希望大家能够共同学习、共同努力、共同进步。
小编在这里祝小伙伴们在未来的日子里都可以 升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰!!
不论遇到什么困难,都不应该成为我们放弃的理由!
### 架构师筑基包括哪些内容
我花了将近半个月时间将:**深入 Java 泛型.、注解深入浅出、并发编程.、数据传输与序列化、Java 虚拟机原理、反射与类加载、高效 IO、Kotlin项目实战等等**Android架构师筑基必备技能整合成了一套系统知识笔记PDF,相信看完这份文档,你将会对这些Android架构师筑基必备技能有着更深入、更系统的理解。
> **由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容**
#### **注:资料与上面思维导图一起看会更容易学习哦!每个点每个细节分支,都有对应的目录内容与知识点!**
![](https://img-blog.csdnimg.cn/img_convert/b52144ba0c5a5a5c9f24be31e6880d71.webp?x-oss-process=image/format,png)
![](https://img-blog.csdnimg.cn/img_convert/e847c52b0700c1c6795f0cb146f713aa.webp?x-oss-process=image/format,png)
这份资料就包含了所有Android初级架构师所需的所有知识!
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
更深入、更系统的理解。
> **由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容**
#### **注:资料与上面思维导图一起看会更容易学习哦!每个点每个细节分支,都有对应的目录内容与知识点!**
[外链图片转存中...(img-rpaQiSaX-1715272062897)]
[外链图片转存中...(img-cpbPZudS-1715272062897)]
这份资料就包含了所有Android初级架构师所需的所有知识!
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**