summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-06-22 01:27:15 -0700
committerJeff Brown <jeffbrown@google.com>2010-06-28 19:10:54 -0700
commit50de30a5230dd15326f8bcbb4beaf617bca265e2 (patch)
tree08220f1667205b8ccd2891ab9eda6276c91571c7 /libs
parenta84687252b1d344f244bf93771d2acd7055d253e (diff)
downloadframeworks_native-50de30a5230dd15326f8bcbb4beaf617bca265e2.zip
frameworks_native-50de30a5230dd15326f8bcbb4beaf617bca265e2.tar.gz
frameworks_native-50de30a5230dd15326f8bcbb4beaf617bca265e2.tar.bz2
Native input event dispatching.
Target identification is now fully native. Fixed a couple of minor issues related to input injection. Native input enabled by default, can be disabled by setting WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH to false. Change-Id: I7edf66ed3e987cc9306ad4743ac57a116af452ff
Diffstat (limited to 'libs')
-rw-r--r--libs/ui/InputDispatcher.cpp86
-rw-r--r--libs/ui/InputManager.cpp4
-rw-r--r--libs/ui/InputReader.cpp55
-rw-r--r--libs/ui/InputTransport.cpp4
4 files changed, 108 insertions, 41 deletions
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index b3103a4..0fc29b2 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -8,25 +8,25 @@
//#define LOG_NDEBUG 0
// Log detailed debug messages about each inbound event notification to the dispatcher.
-#define DEBUG_INBOUND_EVENT_DETAILS 1
+#define DEBUG_INBOUND_EVENT_DETAILS 0
// Log detailed debug messages about each outbound event processed by the dispatcher.
-#define DEBUG_OUTBOUND_EVENT_DETAILS 1
+#define DEBUG_OUTBOUND_EVENT_DETAILS 0
// Log debug messages about batching.
-#define DEBUG_BATCHING 1
+#define DEBUG_BATCHING 0
// Log debug messages about the dispatch cycle.
-#define DEBUG_DISPATCH_CYCLE 1
+#define DEBUG_DISPATCH_CYCLE 0
// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 1
+#define DEBUG_REGISTRATION 0
// Log debug messages about performance statistics.
-#define DEBUG_PERFORMANCE_STATISTICS 1
+#define DEBUG_PERFORMANCE_STATISTICS 0
// Log debug messages about input event injection.
-#define DEBUG_INJECTION 1
+#define DEBUG_INJECTION 0
#include <cutils/log.h>
#include <ui/InputDispatcher.h>
@@ -249,9 +249,7 @@ void InputDispatcher::processKeyLockedInterruptible(
entry->downTime);
#endif
- // TODO: Poke user activity.
-
- if (entry->action == KEY_EVENT_ACTION_DOWN) {
+ if (entry->action == KEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
if (mKeyRepeatState.lastKeyEntry
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
// We have seen two identical key downs in a row which indicates that the device
@@ -277,14 +275,24 @@ void InputDispatcher::processKeyLockedInterruptible(
void InputDispatcher::processKeyRepeatLockedInterruptible(
nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
- // TODO Old WindowManagerServer code sniffs the input queue for following key up
- // events and drops the repeat if one is found. We should do something similar.
- // One good place to do it is in notifyKey as soon as the key up enters the
- // inbound event queue.
+ KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
+
+ // Search the inbound queue for a key up corresponding to this device.
+ // It doesn't make sense to generate a key repeat event if the key is already up.
+ for (EventEntry* queuedEntry = mInboundQueue.head.next;
+ queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
+ if (queuedEntry->type == EventEntry::TYPE_KEY) {
+ KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
+ if (queuedKeyEntry->deviceId == entry->deviceId
+ && entry->action == KEY_EVENT_ACTION_UP) {
+ resetKeyRepeatLocked();
+ return;
+ }
+ }
+ }
// Synthesize a key repeat after the repeat timeout expired.
- // We reuse the previous key entry if otherwise unreferenced.
- KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
+ // Reuse the repeated key entry if it is otherwise unreferenced.
uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
if (entry->refCount == 1) {
entry->eventTime = currentTime;
@@ -366,7 +374,7 @@ void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
entry->downTime, entry->eventTime);
mCurrentInputTargets.clear();
- int32_t injectionResult = mPolicy->getKeyEventTargets(& mReusableKeyEvent,
+ int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
entry->policyFlags, entry->injectorPid, entry->injectorUid,
mCurrentInputTargets);
@@ -375,7 +383,9 @@ void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
setInjectionResultLocked(entry, injectionResult);
- dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+ if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
+ dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+ }
}
void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
@@ -395,7 +405,7 @@ void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
entry->firstSample.pointerCoords);
mCurrentInputTargets.clear();
- int32_t injectionResult = mPolicy->getMotionEventTargets(& mReusableMotionEvent,
+ int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
entry->policyFlags, entry->injectorPid, entry->injectorUid,
mCurrentInputTargets);
@@ -404,7 +414,9 @@ void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
setInjectionResultLocked(entry, injectionResult);
- dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+ if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
+ dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+ }
}
void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
@@ -514,7 +526,7 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
connection->getInputChannelName());
} else if (status == status_t(FAILED_TRANSACTION)) {
LOGD("channel '%s' ~ Could not append motion sample to currently "
- "dispatchedmove event because the event has already been consumed. "
+ "dispatched move event because the event has already been consumed. "
"(Waiting for next dispatch cycle to start.)",
connection->getInputChannelName());
} else {
@@ -1253,9 +1265,37 @@ void InputDispatcher::resetKeyRepeatLocked() {
}
}
+void InputDispatcher::preemptInputDispatch() {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("preemptInputDispatch");
+#endif
+
+ bool preemptedOne = false;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ for (size_t i = 0; i < mActiveConnections.size(); i++) {
+ Connection* connection = mActiveConnections[i];
+ if (connection->hasPendingSyncTarget()) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
+ connection->getInputChannelName());
+#endif
+ connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
+ preemptedOne = true;
+ }
+ }
+ } // release lock
+
+ if (preemptedOne) {
+ // Wake up the poll loop so it can get a head start dispatching the next event.
+ mPollLoop->wake();
+ }
+}
+
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
#if DEBUG_REGISTRATION
- LOGD("channel '%s' - Registered", inputChannel->getName().string());
+ LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
#endif
int receiveFd;
@@ -1288,7 +1328,7 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
#if DEBUG_REGISTRATION
- LOGD("channel '%s' - Unregistered", inputChannel->getName().string());
+ LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
#endif
int32_t receiveFd;
diff --git a/libs/ui/InputManager.cpp b/libs/ui/InputManager.cpp
index 32c58b4..e1d15a4 100644
--- a/libs/ui/InputManager.cpp
+++ b/libs/ui/InputManager.cpp
@@ -85,6 +85,10 @@ int32_t InputManager::injectInputEvent(const InputEvent* event,
return mDispatcher->injectInputEvent(event, injectorPid, injectorUid, sync, timeoutMillis);
}
+void InputManager::preemptInputDispatch() {
+ mDispatcher->preemptInputDispatch();
+}
+
void InputManager::getInputConfiguration(InputConfiguration* outConfiguration) const {
mReader->getCurrentInputConfiguration(outConfiguration);
}
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 1824054..8087f84 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -11,13 +11,13 @@
#define DEBUG_RAW_EVENTS 0
// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 1
+#define DEBUG_HACKS 0
// Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 1
+#define DEBUG_VIRTUAL_KEYS 0
// Log debug messages about pointers.
-#define DEBUG_POINTERS 1
+#define DEBUG_POINTERS 0
// Log debug messages about pointer assignment calculations.
#define DEBUG_POINTER_ASSIGNMENT 0
@@ -630,7 +630,8 @@ void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
int32_t pressure = currentTouch.pointers[currentIndex].pressure;
if (lastTouch.idBits.hasBit(id)) {
- // Pointer still down compute average.
+ // Pointer was down before and is still down now.
+ // Compute average over history trace.
uint32_t start = averagingTouchFilter.historyStart[id];
uint32_t end = averagingTouchFilter.historyEnd[id];
@@ -644,11 +645,15 @@ void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
#endif
if (distance < AVERAGING_DISTANCE_LIMIT) {
+ // Increment end index in preparation for recording new historical data.
end += 1;
if (end > AVERAGING_HISTORY_SIZE) {
end = 0;
}
+ // If the end index has looped back to the start index then we have filled
+ // the historical trace up to the desired size so we drop the historical
+ // data at the start of the trace.
if (end == start) {
start += 1;
if (start > AVERAGING_HISTORY_SIZE) {
@@ -656,23 +661,25 @@ void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
}
}
+ // Add the raw data to the historical trace.
averagingTouchFilter.historyStart[id] = start;
averagingTouchFilter.historyEnd[id] = end;
averagingTouchFilter.historyData[end].pointers[id].x = x;
averagingTouchFilter.historyData[end].pointers[id].y = y;
averagingTouchFilter.historyData[end].pointers[id].pressure = pressure;
+ // Average over all historical positions in the trace by total pressure.
int32_t averagedX = 0;
int32_t averagedY = 0;
int32_t totalPressure = 0;
for (;;) {
int32_t historicalX = averagingTouchFilter.historyData[start].pointers[id].x;
- int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].x;
+ int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].y;
int32_t historicalPressure = averagingTouchFilter.historyData[start]
.pointers[id].pressure;
- averagedX += historicalX;
- averagedY += historicalY;
+ averagedX += historicalX * historicalPressure;
+ averagedY += historicalY * historicalPressure;
totalPressure += historicalPressure;
if (start == end) {
@@ -1144,12 +1151,6 @@ void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
InputDevice* device) {
- static const uint32_t POSITION_FIELDS =
- InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X
- | InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y
- | InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE
- | InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
-
/* Refresh display properties so we can map touch screen coords into display coords */
if (! refreshDisplayProperties()) {
@@ -1167,10 +1168,19 @@ void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
in->current.down = in->accumulator.btnTouch;
}
- if ((fields & POSITION_FIELDS) == POSITION_FIELDS) {
+ if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X) {
in->current.x = in->accumulator.absX;
+ }
+
+ if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y) {
in->current.y = in->accumulator.absY;
+ }
+
+ if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE) {
in->current.pressure = in->accumulator.absPressure;
+ }
+
+ if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH) {
in->current.size = in->accumulator.absToolWidth;
}
@@ -1323,18 +1333,23 @@ bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
void InputReader::dispatchVirtualKey(nsecs_t when,
InputDevice* device, uint32_t policyFlags,
int32_t keyEventAction, int32_t keyEventFlags) {
+ updateExportedVirtualKeyState();
+
int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
int32_t metaState = globalMetaState();
- updateExportedVirtualKeyState();
-
mPolicy->virtualKeyFeedback(when, device->id, keyEventAction, keyEventFlags,
keyCode, scanCode, metaState, downTime);
- mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
- keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+ int32_t policyActions = mPolicy->interceptKey(when, device->id,
+ keyEventAction == KEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
+
+ if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
+ mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
+ keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+ }
}
void InputReader::dispatchTouches(nsecs_t when,
@@ -1609,6 +1624,10 @@ bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
*policyFlags |= POLICY_FLAG_BRIGHT_HERE;
}
+ if (policyActions & InputReaderPolicyInterface::ACTION_INTERCEPT_DISPATCH) {
+ *policyFlags |= POLICY_FLAG_INTERCEPT_DISPATCH;
+ }
+
return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
}
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index b2842d0..f56537a 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -430,10 +430,12 @@ status_t InputPublisher::appendMotionSample(
reinterpret_cast<char*>(mSharedMessage);
if (newBytesUsed > mAshmemSize) {
+#if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ Cannot append motion sample because the shared memory "
"buffer is full. Buffer size: %d bytes, pointers: %d, samples: %d",
mChannel->getName().string(),
mAshmemSize, mMotionEventPointerCount, mSharedMessage->motion.sampleCount);
+#endif
return NO_MEMORY;
}
@@ -444,8 +446,10 @@ status_t InputPublisher::appendMotionSample(
if (errno == EAGAIN) {
// Only possible source of contention is the consumer having consumed (or being in the
// process of consuming) the message and left the semaphore count at 0.
+#if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ Cannot append motion sample because the message has "
"already been consumed.", mChannel->getName().string());
+#endif
return FAILED_TRANSACTION;
} else {
LOGE("channel '%s' publisher ~ Error %d in sem_trywait.",