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
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 32f85b3..57b292b 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -87,6 +87,9 @@
     // Indicates that the screen was dim when the event was received and the event
     // should brighten the device.
     POLICY_FLAG_BRIGHT_HERE = 0x20000000,
+
+    // Indicates that the dispatcher should call back into the policy before dispatching. */
+    POLICY_FLAG_INTERCEPT_DISPATCH = 0x40000000,
 };
 
 /*
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index 511ad20..eb8f820 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -126,21 +126,21 @@
     /* Gets the key repeat timeout or -1 if automatic key repeating is disabled. */
     virtual nsecs_t getKeyRepeatTimeout() = 0;
 
-    /* Gets the input targets for a key event.
+    /* Waits for key event input targets to become available.
      * If the event is being injected, injectorPid and injectorUid should specify the
      * process id and used id of the injecting application, otherwise they should both
      * be -1.
      * Returns one of the INPUT_EVENT_INJECTION_XXX constants. */
-    virtual int32_t getKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
+    virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
             int32_t injectorPid, int32_t injectorUid,
             Vector<InputTarget>& outTargets) = 0;
 
-    /* Gets the input targets for a motion event.
+    /* Waits for motion event targets to become available.
      * If the event is being injected, injectorPid and injectorUid should specify the
      * process id and used id of the injecting application, otherwise they should both
      * be -1.
      * Returns one of the INPUT_EVENT_INJECTION_XXX constants. */
-    virtual int32_t getMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
+    virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
             int32_t injectorPid, int32_t injectorUid,
             Vector<InputTarget>& outTargets) = 0;
 };
@@ -186,6 +186,16 @@
     virtual int32_t injectInputEvent(const InputEvent* event,
             int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) = 0;
 
+    /* Preempts input dispatch in progress by making pending synchronous
+     * dispatches asynchronous instead.  This method is generally called during a focus
+     * transition from one application to the next so as to enable the new application
+     * to start receiving input as soon as possible without having to wait for the
+     * old application to finish up.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void preemptInputDispatch() = 0;
+
     /* Registers or unregister input channels that may be used as targets for input events.
      *
      * These methods may be called on any thread (usually by the input manager).
@@ -233,6 +243,8 @@
     virtual int32_t injectInputEvent(const InputEvent* event,
             int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis);
 
+    virtual void preemptInputDispatch();
+
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
 
diff --git a/include/ui/InputManager.h b/include/ui/InputManager.h
index 7509dd2..e755238 100644
--- a/include/ui/InputManager.h
+++ b/include/ui/InputManager.h
@@ -87,6 +87,14 @@
     virtual int32_t injectInputEvent(const InputEvent* event,
             int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) = 0;
 
+    /* Preempts input dispatch in progress by making pending synchronous
+     * dispatches asynchronous instead.  This method is generally called during a focus
+     * transition from one application to the next so as to enable the new application
+     * to start receiving input as soon as possible without having to wait for the
+     * old application to finish up.
+     */
+    virtual void preemptInputDispatch() = 0;
+
     /* Gets input device configuration. */
     virtual void getInputConfiguration(InputConfiguration* outConfiguration) const = 0;
 
@@ -130,6 +138,8 @@
     virtual int32_t injectInputEvent(const InputEvent* event,
             int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis);
 
+    virtual void preemptInputDispatch();
+
     virtual void getInputConfiguration(InputConfiguration* outConfiguration) const;
     virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
             int32_t scanCode) const;
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index d76b8fe..2093560 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -361,7 +361,11 @@
 
         // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
         // passes through the dispatch pipeline.
-        ACTION_BRIGHT_HERE = 0x00000008
+        ACTION_BRIGHT_HERE = 0x00000008,
+
+        // The input dispatcher should add POLICY_FLAG_INTERCEPT_DISPATCH to the policy flags
+        // it passed through the dispatch pipeline.
+        ACTION_INTERCEPT_DISPATCH = 0x00000010
     };
 
     /* Describes a virtual key. */
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 @@
             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::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 @@
             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 @@
 
     setInjectionResultLocked(entry, injectionResult);
 
-    dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+    if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
+        dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+    }
 }
 
 void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
@@ -395,7 +405,7 @@
             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 @@
 
     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 @@
                         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::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::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 @@
     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 @@
         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 @@
 #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 @@
                     }
                 }
 
+                // 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::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 @@
         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 @@
 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 @@
         *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 @@
             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 @@
             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.",