- 在创建InputDispatcher时会向SurfaceFlinger注册窗口信息监听器mWindowInfoListener
// frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
...
mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
#if defined(__ANDROID__)
SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener);
#endif
...
}
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
binder::Status SurfaceComposerAIDL::addWindowInfosListener(
const sp<gui::IWindowInfosListener>& windowInfosListener,
gui::WindowInfosListenerInfo* outInfo) {
status_t status;
const int pid = IPCThreadState::self()->getCallingPid();
const int uid = IPCThreadState::self()->getCallingUid();
// TODO(b/270566761) update permissions check so that only system_server and shell can add
// WindowInfosListeners
if (uid == AID_SYSTEM || uid == AID_GRAPHICS ||
checkPermission(sAccessSurfaceFlinger, pid, uid)) {
status = mFlinger->addWindowInfosListener(windowInfosListener, outInfo);
} else {
status = PERMISSION_DENIED;
}
return binderStatusFromStatusT(status);
}
status_t SurfaceFlinger::addWindowInfosListener(const sp<IWindowInfosListener>& windowInfosListener,
gui::WindowInfosListenerInfo* outInfo) {
mWindowInfosListenerInvoker->addWindowInfosListener(windowInfosListener, outInfo);
setTransactionFlags(eInputInfoUpdateNeeded);
return NO_ERROR;
}
2. 在合成周期中SurfaceFlinger会调用updateInputFlinger更新Iniput的窗口信息
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
CompositeResultsPerDisplay SurfaceFlinger::composite(
PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters& frameTargeters) {
...
updateInputFlinger(vsyncId, pacesetterTarget.frameBeginTime());
...
}
void SurfaceFlinger::updateInputFlinger(VsyncId vsyncId, TimePoint frameTime) {
if (!mInputFlinger || (!mUpdateInputInfo && mInputWindowCommands.empty())) {
return;
}
ATRACE_CALL();
std::vector<WindowInfo> windowInfos;
std::vector<DisplayInfo> displayInfos;
bool updateWindowInfo = false;
if (mUpdateInputInfo) {
mUpdateInputInfo = false;
updateWindowInfo = true;
// 构造Windowinfos
buildWindowInfos(windowInfos, displayInfos);
}
std::unordered_set<int32_t> visibleWindowIds;
for (WindowInfo& windowInfo : windowInfos) {
if (!windowInfo.inputConfig.test(WindowInfo::InputConfig::NOT_VISIBLE)) {
visibleWindowIds.insert(windowInfo.id);
}
}
bool visibleWindowsChanged = false;
if (visibleWindowIds != mVisibleWindowIds) {
visibleWindowsChanged = true;
mVisibleWindowIds = std::move(visibleWindowIds);
}
BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo,
windowInfos = std::move(windowInfos),
displayInfos = std::move(displayInfos),
inputWindowCommands =
std::move(mInputWindowCommands),
inputFlinger = mInputFlinger, this,
visibleWindowsChanged, vsyncId, frameTime]() {
ATRACE_NAME("BackgroundExecutor::updateInputFlinger");
if (updateWindowInfo) {
// 更新窗口信息
mWindowInfosListenerInvoker
->windowInfosChanged(gui::WindowInfosUpdate{std::move(windowInfos),
std::move(displayInfos),
ftl::to_underlying(vsyncId),
frameTime.ns()},
std::move(
inputWindowCommands.windowInfosReportedListeners),
/* forceImmediateCall= */ visibleWindowsChanged ||
!inputWindowCommands.focusRequests.empty());
} else {
// If there are listeners but no changes to input windows, call the listeners
// immediately.
for (const auto& listener : inputWindowCommands.windowInfosReportedListeners) {
if (IInterface::asBinder(listener)->isBinderAlive()) {
listener->onWindowInfosReported();
}
}
}
for (const auto& focusRequest : inputWindowCommands.focusRequests) {
inputFlinger->setFocusedWindow(focusRequest);
}
}});
mInputWindowCommands.clear();
}
void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
std::vector<DisplayInfo>& outDisplayInfos) {
static size_t sNumWindowInfos = 0;
outWindowInfos.reserve(sNumWindowInfos);
sNumWindowInfos = 0;
if (mLayerLifecycleManagerEnabled) {
mLayerSnapshotBuilder.forEachInputSnapshot(
[&outWindowInfos](const frontend::LayerSnapshot& snapshot) {
outWindowInfos.push_back(snapshot.inputInfo);1. 在创建InputDispatcher时会向SurfaceFlinger注册窗口信息监听器mWindowInfoListener
// frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
...
mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
#if defined(__ANDROID__)
SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener);
#endif
...
}
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
binder::Status SurfaceComposerAIDL::addWindowInfosListener(
const sp<gui::IWindowInfosListener>& windowInfosListener,
gui::WindowInfosListenerInfo* outInfo) {
status_t status;
const int pid = IPCThreadState::self()->getCallingPid();
const int uid = IPCThreadState::self()->getCallingUid();
// TODO(b/270566761) update permissions check so that only system_server and shell can add
// WindowInfosListeners
if (uid == AID_SYSTEM || uid == AID_GRAPHICS ||
checkPermission(sAccessSurfaceFlinger, pid, uid)) {
status = mFlinger->addWindowInfosListener(windowInfosListener, outInfo);
} else {
status = PERMISSION_DENIED;
}
return binderStatusFromStatusT(status);
}
status_t SurfaceFlinger::addWindowInfosListener(const sp<IWindowInfosListener>& windowInfosListener,
gui::WindowInfosListenerInfo* outInfo) {
mWindowInfosListenerInvoker->addWindowInfosListener(windowInfosListener, outInfo);
setTransactionFlags(eInputInfoUpdateNeeded);
return NO_ERROR;
}
2. 在合成周期中SurfaceFlinger会调用updateInputFlinger更新Iniput的窗口信息
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
CompositeResultsPerDisplay SurfaceFlinger::composite(
PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters& frameTargeters) {
...
updateInputFlinger(vsyncId, pacesetterTarget.frameBeginTime());
...
}
void SurfaceFlinger::updateInputFlinger(VsyncId vsyncId, TimePoint frameTime) {
if (!mInputFlinger || (!mUpdateInputInfo && mInputWindowCommands.empty())) {
return;
}
ATRACE_CALL();
std::vector<WindowInfo> windowInfos;
std::vector<DisplayInfo> displayInfos;
bool updateWindowInfo = false;
if (mUpdateInputInfo) {
mUpdateInputInfo = false;
updateWindowInfo = true;
// 构造Windowinfos
buildWindowInfos(windowInfos, displayInfos);
}
std::unordered_set<int32_t> visibleWindowIds;
for (WindowInfo& windowInfo : windowInfos) {
if (!windowInfo.inputConfig.test(WindowInfo::InputConfig::NOT_VISIBLE)) {
visibleWindowIds.insert(windowInfo.id);
}
}
bool visibleWindowsChanged = false;
if (visibleWindowIds != mVisibleWindowIds) {
visibleWindowsChanged = true;
mVisibleWindowIds = std::move(visibleWindowIds);
}
BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo,
windowInfos = std::move(windowInfos),
displayInfos = std::move(displayInfos),
inputWindowCommands =
std::move(mInputWindowCommands),
inputFlinger = mInputFlinger, this,
visibleWindowsChanged, vsyncId, frameTime]() {
ATRACE_NAME("BackgroundExecutor::updateInputFlinger");
if (updateWindowInfo) {
// 更新窗口信息
mWindowInfosListenerInvoker
->windowInfosChanged(gui::WindowInfosUpdate{std::move(windowInfos),
std::move(displayInfos),
ftl::to_underlying(vsyncId),
frameTime.ns()},
std::move(
inputWindowCommands.windowInfosReportedListeners),
/* forceImmediateCall= */ visibleWindowsChanged ||
!inputWindowCommands.focusRequests.empty());
} else {
// If there are listeners but no changes to input windows, call the listeners
// immediately.
for (const auto& listener : inputWindowCommands.windowInfosReportedListeners) {
if (IInterface::asBinder(listener)->isBinderAlive()) {
listener->onWindowInfosReported();
}
}
}
for (const auto& focusRequest : inputWindowCommands.focusRequests) {
inputFlinger->setFocusedWindow(focusRequest);
}
}});
mInputWindowCommands.clear();
}
void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
std::vector<DisplayInfo>& outDisplayInfos) {
static size_t sNumWindowInfos = 0;
outWindowInfos.reserve(sNumWindowInfos);
sNumWindowInfos = 0;
if (mLayerLifecycleManagerEnabled) {
mLayerSnapshotBuilder.forEachInputSnapshot(
[&outWindowInfos](const frontend::LayerSnapshot& snapshot) {
outWindowInfos.push_back(snapshot.inputInfo);
});
} else {
mDrawingState.traverseInReverseZOrder([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) {
if (!layer->needsInputInfo()) return;
const auto opt =
mFrontEndDisplayInfos.get(layer->getLayerStack())
.transform([](const frontend::DisplayInfo& info) {
return Layer::InputDisplayArgs{&info.transform, info.isSecure};
});
outWindowInfos.push_back(layer->fillInputInfo(opt.value_or(Layer::InputDisplayArgs{})));
});
}
sNumWindowInfos = outWindowInfos.size();
outDisplayInfos.reserve(mFrontEndDisplayInfos.size());
for (const auto& [_, info] : mFrontEndDisplayInfos) {
outDisplayInfos.push_back(info.info);
}
}
3. Input收到回调后会将窗口信息保存到mWindowHandlesByDisplay
void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) {
if (auto result = validateWindowInfosUpdate(update); !result.ok()) {
{
// acquire lock
std::scoped_lock _l(mLock);
logDispatchStateLocked();
}
LOG_ALWAYS_FATAL("Incorrect WindowInfosUpdate provided: %s",
result.error().message().c_str());
};
// The listener sends the windows as a flattened array. Separate the windows by display for
// more convenient parsing.
std::unordered_map<ui::LogicalDisplayId, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay;
// 将窗口信息填充到handlesPerDisplay
for (const auto& info : update.windowInfos) {
handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>());
handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info));
}
{ // acquire lock
std::scoped_lock _l(mLock);
// Ensure that we have an entry created for all existing displays so that if a displayId has
// no windows, we can tell that the windows were removed from the display.
for (const auto& [displayId, _] : mWindowHandlesByDisplay) {
handlesPerDisplay[displayId];
}
mDisplayInfos.clear();
for (const auto& displayInfo : update.displayInfos) {
mDisplayInfos.emplace(displayInfo.displayId, displayInfo);
}
// 设置窗口信息
for (const auto& [displayId, handles] : handlesPerDisplay) {
setInputWindowsLocked(handles, displayId);
}
if (update.vsyncId < mWindowInfosVsyncId) {
ALOGE("Received out of order window infos update. Last update vsync id: %" PRId64
", current update vsync id: %" PRId64,
mWindowInfosVsyncId, update.vsyncId);
}
mWindowInfosVsyncId = update.vsyncId;
}
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
}
void InputDispatcher::setInputWindowsLocked(
const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
ui::LogicalDisplayId displayId) {
ScopedSyntheticEventTracer traceContext(mTracer);
// 检查输入窗口的先决条件
for (const sp<WindowInfoHandle>& window : windowInfoHandles) {
const WindowInfo& info = *window->getInfo();
//如果窗口配置有NO_INPUT_CHANNEL,就释放Channel
const bool noInputWindow = info.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
if (noInputWindow && window->getToken() != nullptr) {
ALOGE("%s has feature NO_INPUT_WINDOW, but a non-null token. Clearing",
window->getName().c_str());
window->releaseChannel();
}
// 确保所有间谍窗口都是受信任的覆盖层
LOG_ALWAYS_FATAL_IF(info.isSpy() &&
!info.inputConfig.test(
WindowInfo::InputConfig::TRUSTED_OVERLAY),
"%s has feature SPY, but is not a trusted overlay.",
window->getName().c_str());
// 确保所有触控笔拦截器都是受信任的覆盖层
LOG_ALWAYS_FATAL_IF(info.interceptsStylus() &&
!info.inputConfig.test(
WindowInfo::InputConfig::TRUSTED_OVERLAY),
"%s has feature INTERCEPTS_STYLUS, but is not a trusted overlay.",
window->getName().c_str());
}
// Copy old handles for release if they are no longer present.
const std::vector<sp<WindowInfoHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
const sp<WindowInfoHandle> removedFocusedWindowHandle = getFocusedWindowHandleLocked(displayId);
// 更新窗口信息
updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId);
const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
std::optional<FocusResolver::FocusChanges> changes =
mFocusResolver.setInputWindows(displayId, windowHandles);
if (changes) {
onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
}
// Window已经被移除,所以要从mTouchStatesByDisplay中移除对应的Touched window
if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
TouchState& state = it->second;
for (size_t i = 0; i < state.windows.size();) {
TouchedWindow& touchedWindow = state.windows[i];
if (getWindowHandleLocked(touchedWindow.windowHandle) != nullptr) {
i++;
continue;
}
LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
<< " in display %" << displayId;
CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
"touched window was removed", traceContext.getTracker());
// 给窗口分发一个Cancel事件
synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
// Since we are about to drop the touch, cancel the events for the wallpaper as
// well.oldHandlesById
if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
touchedWindow.windowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
options.deviceId = deviceId;
synthesizeCancelationEventsForWindowLocked(ww, options);
}
}
}
state.windows.erase(state.windows.begin() + i);
}
// 如果拖放的窗口消失,重置拖动状态
// could just clear the state here.
if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
windowHandles.end()) {
ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
sendDropWindowCommandLocked(nullptr, 0, 0);
mDragState.reset();
}
}
// 释放channel
for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) {
if (getWindowHandleLocked(oldWindowHandle) == nullptr) {
if (DEBUG_FOCUS) {
ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
}
oldWindowHandle->releaseChannel();
}
}
}
void InputDispatcher::updateWindowHandlesForDisplayLocked(
const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
ui::LogicalDisplayId displayId) {
if (windowInfoHandles.empty()) {
// Remove all handles on a display if there are no windows left.
mWindowHandlesByDisplay.erase(displayId);
return;
}
// Since we compare the pointer of input window handles across window updates, we need
// to make sure the handle object for the same window stays unchanged across updates.
const std::vector<sp<WindowInfoHandle>>& oldHandles = getWindowHandlesLocked(displayId);
std::unordered_map<int32_t /*id*/, sp<WindowInfoHandle>> oldHandlesById;
for (const sp<WindowInfoHandle>& handle : oldHandles) {
oldHandlesById[handle->getId()] = handle;
}
std::vector<sp<WindowInfoHandle>> newHandles;
for (const sp<WindowInfoHandle>& handle : windowInfoHandles) {
const WindowInfo* info = handle->getInfo();
if (getConnectionLocked(handle->getToken()) == nullptr) {
const bool noInputChannel =
info->inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
const bool canReceiveInput =
!info->inputConfig.test(WindowInfo::InputConfig::NOT_TOUCHABLE) ||
!info->inputConfig.test(WindowInfo::InputConfig::NOT_FOCUSABLE);
if (canReceiveInput && !noInputChannel) {
ALOGV("Window handle %s has no registered input channel",
handle->getName().c_str());
continue;
}
}
if (info->displayId != displayId) {
ALOGE("Window %s updated by wrong display %s, should belong to display %s",
handle->getName().c_str(), displayId.toString().c_str(),
info->displayId.toString().c_str());
continue;
}
if ((oldHandlesById.find(handle->getId()) != oldHandlesById.end()) &&
(oldHandlesById.at(handle->getId())->getToken() == handle->getToken())) {
const sp<WindowInfoHandle>& oldHandle = oldHandlesById.at(handle->getId());
oldHandle->updateFrom(handle);
newHandles.push_back(oldHandle);
} else {
newHandles.push_back(handle);
}
}
// Insert or replace
mWindowHandlesByDisplay[displayId] = newHandles;
}
});
} else {
mDrawingState.traverseInReverseZOrder([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) {
if (!layer->needsInputInfo()) return;
const auto opt =
mFrontEndDisplayInfos.get(layer->getLayerStack())
.transform([](const frontend::DisplayInfo& info) {
return Layer::InputDisplayArgs{&info.transform, info.isSecure};
});
outWindowInfos.push_back(layer->fillInputInfo(opt.value_or(Layer::InputDisplayArgs{})));
});
}
sNumWindowInfos = outWindowInfos.size();
outDisplayInfos.reserve(mFrontEndDisplayInfos.size());
for (const auto& [_, info] : mFrontEndDisplayInfos) {
outDisplayInfos.push_back(info.info);
}
}
3. Input收到回调后会将窗口信息保存到mWindowHandlesByDisplay
void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) {
if (auto result = validateWindowInfosUpdate(update); !result.ok()) {
{
// acquire lock
std::scoped_lock _l(mLock);
logDispatchStateLocked();
}
LOG_ALWAYS_FATAL("Incorrect WindowInfosUpdate provided: %s",
result.error().message().c_str());
};
// The listener sends the windows as a flattened array. Separate the windows by display for
// more convenient parsing.
std::unordered_map<ui::LogicalDisplayId, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay;
// 将窗口信息填充到handlesPerDisplay
for (const auto& info : update.windowInfos) {
handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>());
handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info));
}
{ // acquire lock
std::scoped_lock _l(mLock);
// Ensure that we have an entry created for all existing displays so that if a displayId has
// no windows, we can tell that the windows were removed from the display.
for (const auto& [displayId, _] : mWindowHandlesByDisplay) {
handlesPerDisplay[displayId];
}
mDisplayInfos.clear();
for (const auto& displayInfo : update.displayInfos) {
mDisplayInfos.emplace(displayInfo.displayId, displayInfo);
}
// 设置窗口信息
for (const auto& [displayId, handles] : handlesPerDisplay) {
setInputWindowsLocked(handles, displayId);
}
if (update.vsyncId < mWindowInfosVsyncId) {
ALOGE("Received out of order window infos update. Last update vsync id: %" PRId64
", current update vsync id: %" PRId64,
mWindowInfosVsyncId, update.vsyncId);
}
mWindowInfosVsyncId = update.vsyncId;
}
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
}
void InputDispatcher::setInputWindowsLocked(
const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
ui::LogicalDisplayId displayId) {
ScopedSyntheticEventTracer traceContext(mTracer);
// 检查输入窗口的先决条件
for (const sp<WindowInfoHandle>& window : windowInfoHandles) {
const WindowInfo& info = *window->getInfo();
//如果窗口配置有NO_INPUT_CHANNEL,就释放Channel
const bool noInputWindow = info.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
if (noInputWindow && window->getToken() != nullptr) {
ALOGE("%s has feature NO_INPUT_WINDOW, but a non-null token. Clearing",
window->getName().c_str());
window->releaseChannel();
}
// 确保所有间谍窗口都是受信任的覆盖层
LOG_ALWAYS_FATAL_IF(info.isSpy() &&
!info.inputConfig.test(
WindowInfo::InputConfig::TRUSTED_OVERLAY),
"%s has feature SPY, but is not a trusted overlay.",
window->getName().c_str());
// 确保所有触控笔拦截器都是受信任的覆盖层
LOG_ALWAYS_FATAL_IF(info.interceptsStylus() &&
!info.inputConfig.test(
WindowInfo::InputConfig::TRUSTED_OVERLAY),
"%s has feature INTERCEPTS_STYLUS, but is not a trusted overlay.",
window->getName().c_str());
}
// Copy old handles for release if they are no longer present.
const std::vector<sp<WindowInfoHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
const sp<WindowInfoHandle> removedFocusedWindowHandle = getFocusedWindowHandleLocked(displayId);
// 更新窗口信息
updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId);
const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
std::optional<FocusResolver::FocusChanges> changes =
mFocusResolver.setInputWindows(displayId, windowHandles);
if (changes) {
onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
}
// Window已经被移除,所以要从mTouchStatesByDisplay中移除对应的Touched window
if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
TouchState& state = it->second;
for (size_t i = 0; i < state.windows.size();) {
TouchedWindow& touchedWindow = state.windows[i];
if (getWindowHandleLocked(touchedWindow.windowHandle) != nullptr) {
i++;
continue;
}
LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
<< " in display %" << displayId;
CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
"touched window was removed", traceContext.getTracker());
// 给窗口分发一个Cancel事件
synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
// Since we are about to drop the touch, cancel the events for the wallpaper as
// well.oldHandlesById
if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
touchedWindow.windowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
options.deviceId = deviceId;
synthesizeCancelationEventsForWindowLocked(ww, options);
}
}
}
state.windows.erase(state.windows.begin() + i);
}
// 如果拖放的窗口消失,重置拖动状态
// could just clear the state here.
if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
windowHandles.end()) {
ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
sendDropWindowCommandLocked(nullptr, 0, 0);
mDragState.reset();
}
}
// 释放channel
for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) {
if (getWindowHandleLocked(oldWindowHandle) == nullptr) {
if (DEBUG_FOCUS) {
ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
}
oldWindowHandle->releaseChannel();
}
}
}
void InputDispatcher::updateWindowHandlesForDisplayLocked(
const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
ui::LogicalDisplayId displayId) {
if (windowInfoHandles.empty()) {
// Remove all handles on a display if there are no windows left.
mWindowHandlesByDisplay.erase(displayId);
return;
}
// Since we compare the pointer of input window handles across window updates, we need
// to make sure the handle object for the same window stays unchanged across updates.
const std::vector<sp<WindowInfoHandle>>& oldHandles = getWindowHandlesLocked(displayId);
std::unordered_map<int32_t /*id*/, sp<WindowInfoHandle>> oldHandlesById;
for (const sp<WindowInfoHandle>& handle : oldHandles) {
oldHandlesById[handle->getId()] = handle;
}
std::vector<sp<WindowInfoHandle>> newHandles;
for (const sp<WindowInfoHandle>& handle : windowInfoHandles) {
const WindowInfo* info = handle->getInfo();
if (getConnectionLocked(handle->getToken()) == nullptr) {
const bool noInputChannel =
info->inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
const bool canReceiveInput =
!info->inputConfig.test(WindowInfo::InputConfig::NOT_TOUCHABLE) ||
!info->inputConfig.test(WindowInfo::InputConfig::NOT_FOCUSABLE);
if (canReceiveInput && !noInputChannel) {
ALOGV("Window handle %s has no registered input channel",
handle->getName().c_str());
continue;
}
}
if (info->displayId != displayId) {
ALOGE("Window %s updated by wrong display %s, should belong to display %s",
handle->getName().c_str(), displayId.toString().c_str(),
info->displayId.toString().c_str());
continue;
}
if ((oldHandlesById.find(handle->getId()) != oldHandlesById.end()) &&
(oldHandlesById.at(handle->getId())->getToken() == handle->getToken())) {
const sp<WindowInfoHandle>& oldHandle = oldHandlesById.at(handle->getId());
oldHandle->updateFrom(handle);
newHandles.push_back(oldHandle);
} else {
newHandles.push_back(handle);
}
}
// Insert or replace
mWindowHandlesByDisplay[displayId] = newHandles;
}