Ensure window with NO_INPUT_CHANNEL drops touches
Current behaviour of the system is to drop touches when a window with
feature NO_INPUT_CHANNEL is being touched.
Whether or not this behaviour is correct, first add a test to highlight
the current behaviour.
Bug: 160305383 160425280
Test: atest inputflinger_tests:InputDispatcherMultiWindowOcclusionTests#NoInputChannelFeature_DropsTouches
Test: adb logcat | grep -i input
07-31 17:00:35.499 31208 31213 W InputDispatcher: Window without input channel will not receive the new gesture at 5781842196550
07-31 17:00:35.499 31208 31213 I InputDispatcher: Dropping event because there is no touchable window or gesture monitor at (10, 10) in display 0.
Test: atest inputflinger_tests:InputDispatcherMultiWindowOcclusionTests#NoInputChannelFeature_DropsTouchesWithValidChannel
logs:
07-31 16:58:02.692 30773 30773 E InputDispatcher: Window with input channel and NO_INPUT_CHANNEL has feature NO_INPUT_WINDOW, but a non-null token. Clearing
07-31 16:58:02.693 30773 30778 W InputDispatcher: Window with input channel and NO_INPUT_CHANNEL will not receive the new gesture at 5629036343568
07-31 16:58:02.693 30773 30778 I InputDispatcher: Dropping event because there is no touchable window or gesture monitor at (10, 10) in display 0.
Change-Id: Ied554c3a2100d74ef5fea74897301dded5dc1416
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6c9ac4e..3464b8f 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1687,15 +1687,11 @@
newTouchedWindowHandle = nullptr;
}
+ // Ensure the window has a connection and the connection is responsive
if (newTouchedWindowHandle != nullptr) {
- sp<Connection> connection = getConnectionLocked(newTouchedWindowHandle->getToken());
- if (connection == nullptr) {
- ALOGI("Could not find connection for %s",
- newTouchedWindowHandle->getName().c_str());
- newTouchedWindowHandle = nullptr;
- } else if (!connection->responsive) {
- // don't send the new touch to an unresponsive window
- ALOGW("Unresponsive window %s will not get the new gesture at %" PRIu64,
+ const bool isResponsive = hasResponsiveConnectionLocked(*newTouchedWindowHandle);
+ if (!isResponsive) {
+ ALOGW("%s will not receive the new gesture at %" PRIu64,
newTouchedWindowHandle->getName().c_str(), entry.eventTime);
newTouchedWindowHandle = nullptr;
}
@@ -3678,6 +3674,29 @@
return false;
}
+bool InputDispatcher::hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const {
+ sp<Connection> connection = getConnectionLocked(windowHandle.getToken());
+ const bool noInputChannel =
+ windowHandle.getInfo()->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ if (connection != nullptr && noInputChannel) {
+ ALOGW("%s has feature NO_INPUT_CHANNEL, but it matched to connection %s",
+ windowHandle.getName().c_str(), connection->inputChannel->getName().c_str());
+ return false;
+ }
+
+ if (connection == nullptr) {
+ if (!noInputChannel) {
+ ALOGI("Could not find connection for %s", windowHandle.getName().c_str());
+ }
+ return false;
+ }
+ if (!connection->responsive) {
+ ALOGW("Window %s is not responsive", windowHandle.getName().c_str());
+ return false;
+ }
+ return true;
+}
+
std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked(
const sp<IBinder>& token) const {
size_t count = mInputChannelsByToken.count(token);
@@ -3773,6 +3792,17 @@
ALOGD("setInputWindows displayId=%" PRId32 " %s", displayId, windowList.c_str());
}
+ // Ensure all tokens are null if the window has feature NO_INPUT_CHANNEL
+ for (const sp<InputWindowHandle>& window : inputWindowHandles) {
+ const bool noInputWindow =
+ window->getInfo()->inputFeatures.test(InputWindowInfo::Feature::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();
+ }
+ }
+
// Copy old handles for release if they are no longer present.
const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 982f6af..0ff914f 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -307,6 +307,7 @@
std::shared_ptr<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const
REQUIRES(mLock);
bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
+ bool hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const REQUIRES(mLock);
/*
* Validate and update InputWindowHandles for a given display.