summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVishnu Nair <vishnun@google.com>2022-01-27 22:44:01 +0000
committerVishnu Nair <vishnun@google.com>2022-02-04 17:23:04 +0000
commit212dcf44f696158778939aad4619e320148890eb (patch)
tree23e85723b718d12805dee6e996f07033ed81441b
parent77daf700ce9707d147d2cc3075d6e6bbc1a4280a (diff)
downloadnative-212dcf44f696158778939aad4619e320148890eb.tar.gz
InputFlinger: Add DROP_INPUT feature flags
If a window has the feature DROP_INPUT set, then all touch and key events directed to the window will be dropped. For touch events, the events will not go to the window behind it. The flags are used to enable features that allow for a less trusted interaction model between apps. See the bug for more details. Test: atest libgui_test InputDispatcherDropInputFeatureTest Bug: 197296414 Merged-In: I71d7cf5064c8ce4626cff09b92e15ca38b39cbbe Change-Id: I71d7cf5064c8ce4626cff09b92e15ca38b39cbbe
-rw-r--r--include/input/InputWindow.h2
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp30
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.h3
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp40
4 files changed, 74 insertions, 1 deletions
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index e2c95870cf..cea57ec10d 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -128,7 +128,7 @@ struct InputWindowInfo : public Parcelable {
DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
NO_INPUT_CHANNEL = 0x00000002,
DISABLE_USER_ACTIVITY = 0x00000004,
- INPUT_FEATURE_DROP_INPUT = 0x00000008,
+ DROP_INPUT = 0x00000008,
};
/* These values are filled in by the WM and passed through SurfaceFlinger
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 1899c5f29d..b8f16b0d52 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1802,6 +1802,11 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked(
return InputEventInjectionResult::FAILED;
}
+ // Drop key events if requested by input feature
+ if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) {
+ return InputEventInjectionResult::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
@@ -2027,6 +2032,11 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
}
}
+ // Drop touch events if requested by input feature
+ if (newTouchedWindowHandle != nullptr && shouldDropInput(entry, newTouchedWindowHandle)) {
+ newTouchedWindowHandle = nullptr;
+ }
+
// Drop events that can't be trusted due to occlusion
if (newTouchedWindowHandle != nullptr &&
mBlockUntrustedTouchesMode != BlockUntrustedTouchesMode::DISABLED) {
@@ -2113,6 +2123,13 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
sp<InputWindowHandle> oldTouchedWindowHandle =
tempTouchState.getFirstForegroundWindowHandle();
newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState);
+
+ // Drop touch events if requested by input feature
+ if (newTouchedWindowHandle != nullptr &&
+ shouldDropInput(entry, newTouchedWindowHandle)) {
+ newTouchedWindowHandle = nullptr;
+ }
+
if (oldTouchedWindowHandle != newTouchedWindowHandle &&
oldTouchedWindowHandle != nullptr && newTouchedWindowHandle != nullptr) {
if (DEBUG_FOCUS) {
@@ -6116,6 +6133,19 @@ bool InputDispatcher::waitForIdle() {
return result == std::cv_status::no_timeout;
}
+bool InputDispatcher::shouldDropInput(const EventEntry& entry,
+ const sp<InputWindowHandle>& windowHandle) const {
+ if (windowHandle->getInfo()->inputFeatures.test(InputWindowInfo::Feature::DROP_INPUT)) {
+ ALOGW("Dropping %s event targeting %s as requested by inputFeatures={%s} on display "
+ "%" PRId32 ".",
+ entry.getDescription().c_str(), windowHandle->getName().c_str(),
+ windowHandle->getInfo()->inputFeatures.string().c_str(),
+ windowHandle->getInfo()->displayId);
+ return true;
+ }
+ return false;
+}
+
/**
* Sets focus to the window identified by the token. This must be called
* after updating any input window handles.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 9edf41c9c0..7eb74007f0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -528,6 +528,9 @@ private:
std::string getApplicationWindowLabel(const InputApplicationHandle* applicationHandle,
const sp<InputWindowHandle>& windowHandle);
+ bool shouldDropInput(const EventEntry& entry, const sp<InputWindowHandle>& windowHandle) const
+ REQUIRES(mLock);
+
// Manage the dispatch cycle for a single connection.
// These methods are deliberately not Interruptible because doing all of the work
// with the mutex held makes it easier to ensure that connection invariants are maintained.
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 3a9dede89b..6c2b158882 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -5305,4 +5305,44 @@ TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
mSecondWindow->assertNoEvents();
}
+class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
+
+TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
+ std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
+
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(app, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+ window->setInputFeatures(InputWindowInfo::Feature::DROP_INPUT);
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, app);
+ window->setFocusable(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+ setFocusedWindow(window);
+ window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
+
+ // With the flag set, window should not get any input
+ NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->assertNoEvents();
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->assertNoEvents();
+
+ // With the flag cleared, the window should get input
+ window->setInputFeatures(static_cast<InputWindowInfo::Feature>(0));
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(&keyArgs);
+ window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
+
+ motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ window->assertNoEvents();
+}
+
} // namespace android::inputdispatcher