summaryrefslogtreecommitdiffstats
path: root/services/input
diff options
context:
space:
mode:
Diffstat (limited to 'services/input')
-rw-r--r--services/input/InputDispatcher.cpp81
-rw-r--r--services/input/InputDispatcher.h23
-rw-r--r--services/input/tests/InputDispatcher_test.cpp28
-rw-r--r--services/input/tests/InputReader_test.cpp7
4 files changed, 112 insertions, 27 deletions
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 6ea068a..8363e8b 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -186,7 +186,7 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
mPolicy(policy),
mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(NULL),
- mDispatchEnabled(true), mDispatchFrozen(false),
+ mDispatchEnabled(true), mDispatchFrozen(false), mInputFilterEnabled(false),
mFocusedWindow(NULL),
mFocusedApplication(NULL),
mCurrentInputTargetsValid(false),
@@ -725,7 +725,7 @@ bool InputDispatcher::dispatchKeyLocked(
if (entry->repeatCount == 0
&& entry->action == AKEY_EVENT_ACTION_DOWN
&& (entry->policyFlags & POLICY_FLAG_TRUSTED)
- && !entry->isInjected()) {
+ && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
if (mKeyRepeatState.lastKeyEntry
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
// We have seen two identical key downs in a row which indicates that the device
@@ -2402,7 +2402,18 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so
bool needWake;
{ // acquire lock
- AutoMutex _l(mLock);
+ mLock.lock();
+
+ if (mInputFilterEnabled) {
+ mLock.unlock();
+
+ policyFlags |= POLICY_FLAG_FILTERED;
+ if (!mPolicy->filterInputEvent(&event, policyFlags)) {
+ return; // event was consumed by the filter
+ }
+
+ mLock.lock();
+ }
int32_t repeatCount = 0;
KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
@@ -2410,6 +2421,7 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so
metaState, repeatCount, downTime);
needWake = enqueueInboundEventLocked(newEntry);
+ mLock.unlock();
} // release lock
if (needWake) {
@@ -2452,7 +2464,23 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
bool needWake;
{ // acquire lock
- AutoMutex _l(mLock);
+ mLock.lock();
+
+ if (mInputFilterEnabled) {
+ mLock.unlock();
+
+ MotionEvent event;
+ event.initialize(deviceId, source, action, flags, edgeFlags, metaState, 0, 0,
+ xPrecision, yPrecision, downTime, eventTime,
+ pointerCount, pointerIds, pointerCoords);
+
+ policyFlags |= POLICY_FLAG_FILTERED;
+ if (!mPolicy->filterInputEvent(&event, policyFlags)) {
+ return; // event was consumed by the filter
+ }
+
+ mLock.lock();
+ }
// Attempt batching and streaming of move events.
if (action == AMOTION_EVENT_ACTION_MOVE
@@ -2491,6 +2519,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
LOGD("Appended motion sample onto batch for most recent "
"motion event for this device in the inbound queue.");
#endif
+ mLock.unlock();
return; // done!
}
@@ -2579,6 +2608,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
true /*resumeWithAppendedMotionSample*/);
runCommandsLockedInterruptible();
+ mLock.unlock();
return; // done!
}
}
@@ -2593,6 +2623,7 @@ NoBatchingOrStreaming:;
pointerCount, pointerIds, pointerCoords);
needWake = enqueueInboundEventLocked(newEntry);
+ mLock.unlock();
} // release lock
if (needWake) {
@@ -2612,16 +2643,17 @@ void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t swi
}
int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags) {
#if DEBUG_INBOUND_EVENT_DETAILS
LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
- "syncMode=%d, timeoutMillis=%d",
- event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
+ "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
+ event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
#endif
nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
- uint32_t policyFlags = POLICY_FLAG_INJECTED;
+ policyFlags |= POLICY_FLAG_INJECTED;
if (hasInjectionPermission(injectorPid, injectorUid)) {
policyFlags |= POLICY_FLAG_TRUSTED;
}
@@ -2640,7 +2672,9 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
policyFlags |= POLICY_FLAG_VIRTUAL;
}
- mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
+ if (!(policyFlags & POLICY_FLAG_FILTERED)) {
+ mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
+ }
if (policyFlags & POLICY_FLAG_WOKE_HERE) {
flags |= AKEY_EVENT_FLAG_WOKE_HERE;
@@ -2664,8 +2698,10 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
return INPUT_EVENT_INJECTION_FAILED;
}
- nsecs_t eventTime = motionEvent->getEventTime();
- mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
+ if (!(policyFlags & POLICY_FLAG_FILTERED)) {
+ nsecs_t eventTime = motionEvent->getEventTime();
+ mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
+ }
mLock.lock();
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
@@ -2780,7 +2816,8 @@ void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t inject
injectionResult, injectionState->injectorPid, injectionState->injectorUid);
#endif
- if (injectionState->injectionIsAsync) {
+ if (injectionState->injectionIsAsync
+ && !(entry->policyFlags & POLICY_FLAG_FILTERED)) {
// Log the outcome since the injector did not wait for the injection result.
switch (injectionResult) {
case INPUT_EVENT_INJECTION_SUCCEEDED:
@@ -2982,6 +3019,26 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
}
}
+void InputDispatcher::setInputFilterEnabled(bool enabled) {
+#if DEBUG_FOCUS
+ LOGD("setInputFilterEnabled: enabled=%d", enabled);
+#endif
+
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mInputFilterEnabled == enabled) {
+ return;
+ }
+
+ mInputFilterEnabled = enabled;
+ resetAndDropEverythingLocked("input filter is being enabled or disabled");
+ } // release lock
+
+ // Wake up poll loop since there might be work to do to drop everything.
+ mLooper->wake();
+}
+
bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel) {
#if DEBUG_FOCUS
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 48e4d43..162e606 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -176,6 +176,13 @@ public:
*/
virtual int32_t getMaxEventsPerSecond() = 0;
+ /* Filters an input event.
+ * Return true to dispatch the event unmodified, false to consume the event.
+ * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
+ * to injectInputEvent.
+ */
+ virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;
+
/* Intercepts a key event immediately before queueing it.
* The policy can use this method as an opportunity to perform power management functions
* and early event preprocessing such as updating policy flags.
@@ -266,7 +273,8 @@ public:
* This method may be called on any thread (usually by the input manager).
*/
virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0;
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags) = 0;
/* Sets the list of input windows.
*
@@ -286,6 +294,14 @@ public:
*/
virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
+ /* Sets whether input event filtering is enabled.
+ * When enabled, incoming input events are sent to the policy's filterInputEvent
+ * method instead of being dispatched. The filter is expected to use
+ * injectInputEvent to inject the events it would like to have dispatched.
+ * It should include POLICY_FLAG_FILTERED in the policy flags during injection.
+ */
+ virtual void setInputFilterEnabled(bool enabled) = 0;
+
/* Transfers touch focus from the window associated with one channel to the
* window associated with the other channel.
*
@@ -345,11 +361,13 @@ public:
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ;
virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags);
virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
virtual void setFocusedApplication(const InputApplication* inputApplication);
virtual void setInputDispatchMode(bool enabled, bool frozen);
+ virtual void setInputFilterEnabled(bool enabled);
virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel);
@@ -863,6 +881,7 @@ private:
// Dispatch state.
bool mDispatchEnabled;
bool mDispatchFrozen;
+ bool mInputFilterEnabled;
Vector<InputWindow> mWindows;
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 2f846c4..3650da0 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -67,6 +67,10 @@ private:
return 60;
}
+ virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
+ return true;
+ }
+
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
}
@@ -124,7 +128,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
/*action*/ -1, 0,
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject key events with undefined action.";
// Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
@@ -132,7 +136,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
AKEY_EVENT_ACTION_MULTIPLE, 0,
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject key events with ACTION_MULTIPLE.";
}
@@ -150,7 +154,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
@@ -160,7 +164,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too large.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
@@ -169,7 +173,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
@@ -179,7 +183,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too large.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
@@ -188,7 +192,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
@@ -197,7 +201,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with 0 pointers.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
@@ -205,7 +209,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with more than MAX_POINTERS pointers.";
// Rejects motion events with invalid pointer ids.
@@ -215,7 +219,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer ids less than 0.";
pointerIds[0] = MAX_POINTER_ID + 1;
@@ -224,7 +228,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
// Rejects motion events with duplicate pointer ids.
@@ -235,7 +239,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerIds, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with duplicate pointer ids.";
}
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 60549c6..4c5f239 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -369,7 +369,8 @@ private:
}
virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags) {
ADD_FAILURE() << "Should never be called by input reader.";
return INPUT_EVENT_INJECTION_FAILED;
}
@@ -386,6 +387,10 @@ private:
ADD_FAILURE() << "Should never be called by input reader.";
}
+ virtual void setInputFilterEnabled(bool enabled) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ }
+
virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel) {
ADD_FAILURE() << "Should never be called by input reader.";