More native input event dispatching.

Added ANRs handling.
Added event injection.
Fixed a NPE ActivityManagerServer writing ANRs to the drop box.
Fixed HOME key interception.
Fixed trackball reporting.
Fixed pointer rotation in landscape mode.

Change-Id: I50340f559f22899ab924e220a78119ffc79469b7
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 14dcada..2ad3382 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -25,6 +25,9 @@
 // Log debug messages about performance statistics.
 #define DEBUG_PERFORMANCE_STATISTICS 1
 
+// Log debug messages about input event injection.
+#define DEBUG_INJECTION 1
+
 #include <cutils/log.h>
 #include <ui/InputDispatcher.h>
 
@@ -43,6 +46,10 @@
             || keyCode == KEYCODE_DPAD_RIGHT;
 }
 
+static inline nsecs_t now() {
+    return systemTime(SYSTEM_TIME_MONOTONIC);
+}
+
 // --- InputDispatcher ---
 
 InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
@@ -84,7 +91,7 @@
     nsecs_t nextWakeupTime = LONG_LONG_MAX;
     { // acquire lock
         AutoMutex _l(mLock);
-        currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+        currentTime = now();
 
         // Reset the key repeat timer whenever we disallow key events, even if the next event
         // is not a key.  This is to ensure that we abort a key repeat if the device is just coming
@@ -94,33 +101,33 @@
             resetKeyRepeatLocked();
         }
 
-        // Process timeouts for all connections and determine if there are any synchronous
-        // event dispatches pending.
+        // Detect and process timeouts for all connections and determine if there are any
+        // synchronous event dispatches pending.  This step is entirely non-interruptible.
         bool hasPendingSyncTarget = false;
-        for (size_t i = 0; i < mActiveConnections.size(); ) {
+        size_t activeConnectionCount = mActiveConnections.size();
+        for (size_t i = 0; i < activeConnectionCount; i++) {
             Connection* connection = mActiveConnections.itemAt(i);
 
-            nsecs_t connectionTimeoutTime  = connection->nextTimeoutTime;
-            if (connectionTimeoutTime <= currentTime) {
-                bool deactivated = timeoutDispatchCycleLocked(currentTime, connection);
-                if (deactivated) {
-                    // Don't increment i because the connection has been removed
-                    // from mActiveConnections (hence, deactivated).
-                    continue;
-                }
-            }
-
-            if (connectionTimeoutTime < nextWakeupTime) {
-                nextWakeupTime = connectionTimeoutTime;
-            }
-
             if (connection->hasPendingSyncTarget()) {
                 hasPendingSyncTarget = true;
             }
 
-            i += 1;
+            nsecs_t connectionTimeoutTime  = connection->nextTimeoutTime;
+            if (connectionTimeoutTime <= currentTime) {
+                mTimedOutConnections.add(connection);
+            } else if (connectionTimeoutTime < nextWakeupTime) {
+                nextWakeupTime = connectionTimeoutTime;
+            }
         }
 
+        size_t timedOutConnectionCount = mTimedOutConnections.size();
+        for (size_t i = 0; i < timedOutConnectionCount; i++) {
+            Connection* connection = mTimedOutConnections.itemAt(i);
+            timeoutDispatchCycleLocked(currentTime, connection);
+            skipPoll = true;
+        }
+        mTimedOutConnections.clear();
+
         // If we don't have a pending sync target, then we can begin delivering a new event.
         // (Otherwise we wait for dispatch to complete for that target.)
         if (! hasPendingSyncTarget) {
@@ -177,6 +184,11 @@
 
         // Run any deferred commands.
         skipPoll |= runCommandsLockedInterruptible();
+
+        // Wake up synchronization waiters, if needed.
+        if (isFullySynchronizedLocked()) {
+            mFullySynchronizedCondition.broadcast();
+        }
     } // release lock
 
     // If we dispatched anything, don't poll just now.  Wait for the next iteration.
@@ -202,6 +214,7 @@
         Command command = commandEntry->command;
         (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
 
+        commandEntry->connection.clear();
         mAllocator.releaseCommandEntry(commandEntry);
     } while (! mCommandQueue.isEmpty());
     return true;
@@ -272,28 +285,23 @@
     // Synthesize a key repeat after the repeat timeout expired.
     // We reuse the previous key entry if otherwise unreferenced.
     KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
+    uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
     if (entry->refCount == 1) {
+        entry->eventTime = currentTime;
+        entry->downTime = currentTime;
+        entry->policyFlags = policyFlags;
         entry->repeatCount += 1;
     } else {
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry();
-        newEntry->deviceId = entry->deviceId;
-        newEntry->nature = entry->nature;
-        newEntry->policyFlags = entry->policyFlags;
-        newEntry->action = entry->action;
-        newEntry->flags = entry->flags;
-        newEntry->keyCode = entry->keyCode;
-        newEntry->scanCode = entry->scanCode;
-        newEntry->metaState = entry->metaState;
-        newEntry->repeatCount = entry->repeatCount + 1;
+        KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
+                entry->deviceId, entry->nature, policyFlags,
+                entry->action, entry->flags, entry->keyCode, entry->scanCode,
+                entry->metaState, entry->repeatCount + 1, currentTime);
 
         mKeyRepeatState.lastKeyEntry = newEntry;
         mAllocator.releaseKeyEntry(entry);
 
         entry = newEntry;
     }
-    entry->eventTime = currentTime;
-    entry->downTime = currentTime;
-    entry->policyFlags = 0;
 
     mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
 
@@ -358,12 +366,15 @@
             entry->downTime, entry->eventTime);
 
     mCurrentInputTargets.clear();
-    mPolicy->getKeyEventTargets(& mReusableKeyEvent, entry->policyFlags,
+    int32_t injectionResult = mPolicy->getKeyEventTargets(& mReusableKeyEvent,
+            entry->policyFlags, entry->injectorPid, entry->injectorUid,
             mCurrentInputTargets);
 
     mLock.lock();
     mCurrentInputTargetsValid = true;
 
+    setInjectionResultLocked(entry, injectionResult);
+
     dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
 }
 
@@ -384,12 +395,15 @@
             entry->firstSample.pointerCoords);
 
     mCurrentInputTargets.clear();
-    mPolicy->getMotionEventTargets(& mReusableMotionEvent, entry->policyFlags,
+    int32_t injectionResult = mPolicy->getMotionEventTargets(& mReusableMotionEvent,
+            entry->policyFlags, entry->injectorPid, entry->injectorUid,
             mCurrentInputTargets);
 
     mLock.lock();
     mCurrentInputTargetsValid = true;
 
+    setInjectionResultLocked(entry, injectionResult);
+
     dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
 }
 
@@ -410,7 +424,7 @@
                 inputTarget.inputChannel->getReceivePipeFd());
         if (connectionIndex >= 0) {
             sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-            prepareDispatchCycleLocked(currentTime, connection.get(), eventEntry, & inputTarget,
+            prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
                     resumeWithAppendedMotionSample);
         } else {
             LOGW("Framework requested delivery of an input event to channel '%s' but it "
@@ -420,8 +434,8 @@
     }
 }
 
-void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
-        EventEntry* eventEntry, const InputTarget* inputTarget,
+void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
         bool resumeWithAppendedMotionSample) {
 #if DEBUG_DISPATCH_CYCLE
     LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
@@ -547,12 +561,13 @@
 
     // If the outbound queue was previously empty, start the dispatch cycle going.
     if (wasEmpty) {
-        activateConnectionLocked(connection);
+        activateConnectionLocked(connection.get());
         startDispatchCycleLocked(currentTime, connection);
     }
 }
 
-void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
+void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
 #if DEBUG_DISPATCH_CYCLE
     LOGD("channel '%s' ~ startDispatchCycle",
             connection->getInputChannelName());
@@ -682,13 +697,14 @@
     connection->lastDispatchTime = currentTime;
 
     nsecs_t timeout = dispatchEntry->timeout;
-    connection->nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
+    connection->setNextTimeoutTime(currentTime, timeout);
 
     // Notify other system components.
     onDispatchCycleStartedLocked(currentTime, connection);
 }
 
-void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
+void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
 #if DEBUG_DISPATCH_CYCLE
     LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
             "%01.1fms since dispatch",
@@ -756,31 +772,48 @@
     }
 
     // Outbound queue is empty, deactivate the connection.
-    deactivateConnectionLocked(connection);
+    deactivateConnectionLocked(connection.get());
 }
 
-bool InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
+void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
 #if DEBUG_DISPATCH_CYCLE
     LOGD("channel '%s' ~ timeoutDispatchCycle",
             connection->getInputChannelName());
 #endif
 
     if (connection->status != Connection::STATUS_NORMAL) {
-        return false;
+        return;
     }
 
     // Enter the not responding state.
     connection->status = Connection::STATUS_NOT_RESPONDING;
     connection->lastANRTime = currentTime;
-    bool deactivated = abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
 
     // Notify other system components.
+    // This enqueues a command which will eventually either call
+    // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
     onDispatchCycleANRLocked(currentTime, connection);
-    return deactivated;
 }
 
-bool InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
-        bool broken) {
+void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, nsecs_t newTimeout) {
+#if DEBUG_DISPATCH_CYCLE
+    LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
+            connection->getInputChannelName());
+#endif
+
+    if (connection->status != Connection::STATUS_NOT_RESPONDING) {
+        return;
+    }
+
+    // Resume normal dispatch.
+    connection->status = Connection::STATUS_NORMAL;
+    connection->setNextTimeoutTime(currentTime, newTimeout);
+}
+
+void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, bool broken) {
 #if DEBUG_DISPATCH_CYCLE
     LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
             connection->getInputChannelName(), broken ? "true" : "false");
@@ -790,14 +823,13 @@
     connection->nextTimeoutTime = LONG_LONG_MAX;
 
     // Clear the outbound queue.
-    bool deactivated = ! connection->outboundQueue.isEmpty();
-    if (deactivated) {
+    if (! connection->outboundQueue.isEmpty()) {
         do {
             DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
             mAllocator.releaseDispatchEntry(dispatchEntry);
         } while (! connection->outboundQueue.isEmpty());
 
-        deactivateConnectionLocked(connection);
+        deactivateConnectionLocked(connection.get());
     }
 
     // Handle the case where the connection appears to be unrecoverably broken.
@@ -811,8 +843,6 @@
             onDispatchCycleBrokenLocked(currentTime, connection);
         }
     }
-
-    return deactivated;
 }
 
 bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
@@ -828,13 +858,13 @@
             return false; // remove the callback
         }
 
-        nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+        nsecs_t currentTime = now();
 
         sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
         if (events & (POLLERR | POLLHUP | POLLNVAL)) {
             LOGE("channel '%s' ~ Consumer closed input channel or an error occurred.  "
                     "events=0x%x", connection->getInputChannelName(), events);
-            d->abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
+            d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
             d->runCommandsLockedInterruptible();
             return false; // remove the callback
         }
@@ -849,12 +879,12 @@
         if (status) {
             LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
                     connection->getInputChannelName(), status);
-            d->abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
+            d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
             d->runCommandsLockedInterruptible();
             return false; // remove the callback
         }
 
-        d->finishDispatchCycleLocked(currentTime, connection.get());
+        d->finishDispatchCycleLocked(currentTime, connection);
         d->runCommandsLockedInterruptible();
         return true;
     } // release lock
@@ -869,8 +899,7 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
-        ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry();
-        newEntry->eventTime = eventTime;
+        ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
 
         wasEmpty = mInboundQueue.isEmpty();
         mInboundQueue.enqueueAtTail(newEntry);
@@ -902,6 +931,9 @@
                     LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
                             keyEntry->keyCode, keyEntry->action);
                     mInboundQueue.dequeue(keyEntry);
+
+                    setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
+
                     mAllocator.releaseKeyEntry(keyEntry);
                 } else {
                     // stop at last non-movement key
@@ -928,18 +960,10 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry();
-        newEntry->eventTime = eventTime;
-        newEntry->deviceId = deviceId;
-        newEntry->nature = nature;
-        newEntry->policyFlags = policyFlags;
-        newEntry->action = action;
-        newEntry->flags = flags;
-        newEntry->keyCode = keyCode;
-        newEntry->scanCode = scanCode;
-        newEntry->metaState = metaState;
-        newEntry->repeatCount = 0;
-        newEntry->downTime = downTime;
+        int32_t repeatCount = 0;
+        KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
+                deviceId, nature, policyFlags, action, flags, keyCode, scanCode,
+                metaState, repeatCount, downTime);
 
         wasEmpty = mInboundQueue.isEmpty();
         mInboundQueue.enqueueAtTail(newEntry);
@@ -992,7 +1016,8 @@
                 }
 
                 if (motionEntry->action != MOTION_EVENT_ACTION_MOVE
-                        || motionEntry->pointerCount != pointerCount) {
+                        || motionEntry->pointerCount != pointerCount
+                        || motionEntry->isInjected()) {
                     // Last motion event in the queue for this device is not compatible for
                     // appending new samples.  Stop here.
                     goto NoBatchingOrStreaming;
@@ -1000,7 +1025,7 @@
 
                 // The last motion event is a move and is compatible for appending.
                 // Do the batching magic.
-                mAllocator.appendMotionSample(motionEntry, eventTime, pointerCount, pointerCoords);
+                mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
 #if DEBUG_BATCHING
                 LOGD("Appended motion sample onto batch for most recent "
                         "motion event for this device in the inbound queue.");
@@ -1053,18 +1078,19 @@
                                     dispatchEntry->eventEntry);
                             if (syncedMotionEntry->action != MOTION_EVENT_ACTION_MOVE
                                     || syncedMotionEntry->deviceId != deviceId
-                                    || syncedMotionEntry->pointerCount != pointerCount) {
+                                    || syncedMotionEntry->pointerCount != pointerCount
+                                    || syncedMotionEntry->isInjected()) {
                                 goto NoBatchingOrStreaming;
                             }
 
                             // Found synced move entry.  Append sample and resume dispatch.
                             mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
-                                    pointerCount, pointerCoords);
+                                    pointerCoords);
     #if DEBUG_BATCHING
                             LOGD("Appended motion sample onto batch for most recent synchronously "
                                     "dispatched motion event for this device in the outbound queues.");
     #endif
-                            nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+                            nsecs_t currentTime = now();
                             dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
                                     true /*resumeWithAppendedMotionSample*/);
 
@@ -1079,24 +1105,10 @@
         }
 
         // Just enqueue a new motion event.
-        MotionEntry* newEntry = mAllocator.obtainMotionEntry();
-        newEntry->eventTime = eventTime;
-        newEntry->deviceId = deviceId;
-        newEntry->nature = nature;
-        newEntry->policyFlags = policyFlags;
-        newEntry->action = action;
-        newEntry->metaState = metaState;
-        newEntry->edgeFlags = edgeFlags;
-        newEntry->xPrecision = xPrecision;
-        newEntry->yPrecision = yPrecision;
-        newEntry->downTime = downTime;
-        newEntry->pointerCount = pointerCount;
-        newEntry->firstSample.eventTime = eventTime;
-        newEntry->lastSample = & newEntry->firstSample;
-        for (uint32_t i = 0; i < pointerCount; i++) {
-            newEntry->pointerIds[i] = pointerIds[i];
-            newEntry->firstSample.pointerCoords[i] = pointerCoords[i];
-        }
+        MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
+                deviceId, nature, policyFlags, action, metaState, edgeFlags,
+                xPrecision, yPrecision, downTime,
+                pointerCount, pointerIds, pointerCoords);
 
         wasEmpty = mInboundQueue.isEmpty();
         mInboundQueue.enqueueAtTail(newEntry);
@@ -1107,6 +1119,133 @@
     }
 }
 
+int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
+        int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
+            "sync=%d, timeoutMillis=%d",
+            event->getType(), injectorPid, injectorUid, sync, timeoutMillis);
+#endif
+
+    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
+
+    EventEntry* injectedEntry;
+    bool wasEmpty;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        injectedEntry = createEntryFromInputEventLocked(event);
+        injectedEntry->refCount += 1;
+        injectedEntry->injectorPid = injectorPid;
+        injectedEntry->injectorUid = injectorUid;
+
+        wasEmpty = mInboundQueue.isEmpty();
+        mInboundQueue.enqueueAtTail(injectedEntry);
+
+    } // release lock
+
+    if (wasEmpty) {
+        mPollLoop->wake();
+    }
+
+    int32_t injectionResult;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        for (;;) {
+            injectionResult = injectedEntry->injectionResult;
+            if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
+                break;
+            }
+
+            nsecs_t remainingTimeout = endTime - now();
+            if (remainingTimeout <= 0) {
+                injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
+                sync = false;
+                break;
+            }
+
+            mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
+        }
+
+        if (sync) {
+            while (! isFullySynchronizedLocked()) {
+                nsecs_t remainingTimeout = endTime - now();
+                if (remainingTimeout <= 0) {
+                    injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
+                    break;
+                }
+
+                mFullySynchronizedCondition.waitRelative(mLock, remainingTimeout);
+            }
+        }
+
+        mAllocator.releaseEventEntry(injectedEntry);
+    } // release lock
+
+    return injectionResult;
+}
+
+void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
+    if (entry->isInjected()) {
+#if DEBUG_INJECTION
+        LOGD("Setting input event injection result to %d.  "
+                "injectorPid=%d, injectorUid=%d",
+                 injectionResult, entry->injectorPid, entry->injectorUid);
+#endif
+
+        entry->injectionResult = injectionResult;
+        mInjectionResultAvailableCondition.broadcast();
+    }
+}
+
+bool InputDispatcher::isFullySynchronizedLocked() {
+    return mInboundQueue.isEmpty() && mActiveConnections.isEmpty();
+}
+
+InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
+        const InputEvent* event) {
+    switch (event->getType()) {
+    case INPUT_EVENT_TYPE_KEY: {
+        const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
+        uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
+
+        KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
+                keyEvent->getDeviceId(), keyEvent->getNature(), policyFlags,
+                keyEvent->getAction(), keyEvent->getFlags(),
+                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
+                keyEvent->getRepeatCount(), keyEvent->getDownTime());
+        return keyEntry;
+    }
+
+    case INPUT_EVENT_TYPE_MOTION: {
+        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
+        uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
+
+        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
+        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
+        size_t pointerCount = motionEvent->getPointerCount();
+
+        MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
+                motionEvent->getDeviceId(), motionEvent->getNature(), policyFlags,
+                motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
+                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
+                motionEvent->getDownTime(), uint32_t(pointerCount),
+                motionEvent->getPointerIds(), samplePointerCoords);
+        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
+            sampleEventTimes += 1;
+            samplePointerCoords += pointerCount;
+            mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
+        }
+        return motionEntry;
+    }
+
+    default:
+        assert(false);
+        return NULL;
+    }
+}
+
 void InputDispatcher::resetKeyRepeatLocked() {
     if (mKeyRepeatState.lastKeyEntry) {
         mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
@@ -1169,8 +1308,8 @@
 
         connection->status = Connection::STATUS_ZOMBIE;
 
-        nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
-        abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
+        nsecs_t currentTime = now();
+        abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
 
         runCommandsLockedInterruptible();
     } // release lock
@@ -1202,11 +1341,11 @@
 }
 
 void InputDispatcher::onDispatchCycleStartedLocked(
-        nsecs_t currentTime, Connection* connection) {
+        nsecs_t currentTime, const sp<Connection>& connection) {
 }
 
 void InputDispatcher::onDispatchCycleFinishedLocked(
-        nsecs_t currentTime, Connection* connection, bool recoveredFromANR) {
+        nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
     if (recoveredFromANR) {
         LOGI("channel '%s' ~ Recovered from ANR.  %01.1fms since event, "
                 "%01.1fms since dispatch, %01.1fms since ANR",
@@ -1217,12 +1356,12 @@
 
         CommandEntry* commandEntry = postCommandLocked(
                 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
-        commandEntry->inputChannel = connection->inputChannel;
+        commandEntry->connection = connection;
     }
 }
 
 void InputDispatcher::onDispatchCycleANRLocked(
-        nsecs_t currentTime, Connection* connection) {
+        nsecs_t currentTime, const sp<Connection>& connection) {
     LOGI("channel '%s' ~ Not responding!  %01.1fms since event, %01.1fms since dispatch",
             connection->getInputChannelName(),
             connection->getEventLatencyMillis(currentTime),
@@ -1230,47 +1369,64 @@
 
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
-    commandEntry->inputChannel = connection->inputChannel;
+    commandEntry->connection = connection;
 }
 
 void InputDispatcher::onDispatchCycleBrokenLocked(
-        nsecs_t currentTime, Connection* connection) {
+        nsecs_t currentTime, const sp<Connection>& connection) {
     LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
             connection->getInputChannelName());
 
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
-    commandEntry->inputChannel = connection->inputChannel;
+    commandEntry->connection = connection;
 }
 
 void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
         CommandEntry* commandEntry) {
-    mLock.unlock();
+    sp<Connection> connection = commandEntry->connection;
 
-    mPolicy->notifyInputChannelBroken(commandEntry->inputChannel);
-    commandEntry->inputChannel.clear();
+    if (connection->status != Connection::STATUS_ZOMBIE) {
+        mLock.unlock();
 
-    mLock.lock();
+        mPolicy->notifyInputChannelBroken(connection->inputChannel);
+
+        mLock.lock();
+    }
 }
 
 void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
         CommandEntry* commandEntry) {
-    mLock.unlock();
+    sp<Connection> connection = commandEntry->connection;
 
-    mPolicy->notifyInputChannelANR(commandEntry->inputChannel);
-    commandEntry->inputChannel.clear();
+    if (connection->status != Connection::STATUS_ZOMBIE) {
+        mLock.unlock();
 
-    mLock.lock();
+        nsecs_t newTimeout;
+        bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
+
+        mLock.lock();
+
+        nsecs_t currentTime = now();
+        if (resume) {
+            resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
+        } else {
+            abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
+        }
+    }
 }
 
 void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
         CommandEntry* commandEntry) {
-    mLock.unlock();
+    sp<Connection> connection = commandEntry->connection;
 
-    mPolicy->notifyInputChannelRecoveredFromANR(commandEntry->inputChannel);
-    commandEntry->inputChannel.clear();
+    if (connection->status != Connection::STATUS_ZOMBIE) {
+        mLock.unlock();
 
-    mLock.lock();
+        mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
+
+        mLock.lock();
+    }
 }
 
 
@@ -1279,29 +1435,69 @@
 InputDispatcher::Allocator::Allocator() {
 }
 
+void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
+        nsecs_t eventTime) {
+    entry->type = type;
+    entry->refCount = 1;
+    entry->dispatchInProgress = false;
+    entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
+    entry->injectorPid = -1;
+    entry->injectorUid = -1;
+}
+
 InputDispatcher::ConfigurationChangedEntry*
-InputDispatcher::Allocator::obtainConfigurationChangedEntry() {
+InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
     ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
-    entry->refCount = 1;
-    entry->type = EventEntry::TYPE_CONFIGURATION_CHANGED;
-    entry->dispatchInProgress = false;
+    initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
     return entry;
 }
 
-InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry() {
+InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
+        int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
+        int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+        int32_t repeatCount, nsecs_t downTime) {
     KeyEntry* entry = mKeyEntryPool.alloc();
-    entry->refCount = 1;
-    entry->type = EventEntry::TYPE_KEY;
-    entry->dispatchInProgress = false;
+    initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
+
+    entry->deviceId = deviceId;
+    entry->nature = nature;
+    entry->policyFlags = policyFlags;
+    entry->action = action;
+    entry->flags = flags;
+    entry->keyCode = keyCode;
+    entry->scanCode = scanCode;
+    entry->metaState = metaState;
+    entry->repeatCount = repeatCount;
+    entry->downTime = downTime;
     return entry;
 }
 
-InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry() {
+InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
+        int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
+        int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
+        nsecs_t downTime, uint32_t pointerCount,
+        const int32_t* pointerIds, const PointerCoords* pointerCoords) {
     MotionEntry* entry = mMotionEntryPool.alloc();
-    entry->refCount = 1;
-    entry->type = EventEntry::TYPE_MOTION;
+    initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
+
+    entry->eventTime = eventTime;
+    entry->deviceId = deviceId;
+    entry->nature = nature;
+    entry->policyFlags = policyFlags;
+    entry->action = action;
+    entry->metaState = metaState;
+    entry->edgeFlags = edgeFlags;
+    entry->xPrecision = xPrecision;
+    entry->yPrecision = yPrecision;
+    entry->downTime = downTime;
+    entry->pointerCount = pointerCount;
+    entry->firstSample.eventTime = eventTime;
     entry->firstSample.next = NULL;
-    entry->dispatchInProgress = false;
+    entry->lastSample = & entry->firstSample;
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        entry->pointerIds[i] = pointerIds[i];
+        entry->firstSample.pointerCoords[i] = pointerCoords[i];
+    }
     return entry;
 }
 
@@ -1379,10 +1575,11 @@
 }
 
 void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
-        nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords) {
+        nsecs_t eventTime, const PointerCoords* pointerCoords) {
     MotionSample* sample = mMotionSamplePool.alloc();
     sample->eventTime = eventTime;
-    for (int32_t i = 0; i < pointerCount; i++) {
+    uint32_t pointerCount = motionEntry->pointerCount;
+    for (uint32_t i = 0; i < pointerCount; i++) {
         sample->pointerCoords[i] = pointerCoords[i];
     }
 
@@ -1407,6 +1604,10 @@
     return inputPublisher.initialize();
 }
 
+void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
+    nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
+}
+
 const char* InputDispatcher::Connection::getStatusLabel() const {
     switch (status) {
     case STATUS_NORMAL:
diff --git a/libs/ui/InputManager.cpp b/libs/ui/InputManager.cpp
index 7538dd0..32c58b4 100644
--- a/libs/ui/InputManager.cpp
+++ b/libs/ui/InputManager.cpp
@@ -80,6 +80,11 @@
     return mDispatcher->unregisterInputChannel(inputChannel);
 }
 
+int32_t InputManager::injectInputEvent(const InputEvent* event,
+        int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) {
+    return mDispatcher->injectInputEvent(event, injectorPid, injectorUid, sync, timeoutMillis);
+}
+
 void InputManager::getInputConfiguration(InputConfiguration* outConfiguration) const {
     mReader->getCurrentInputConfiguration(outConfiguration);
 }
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 5a280ae..1824054 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -1444,7 +1444,7 @@
         case InputReaderPolicyInterface::ROTATION_90: {
             float xTemp = x;
             x = y;
-            y = mDisplayHeight - xTemp;
+            y = mDisplayWidth - xTemp;
             break;
         }
         case InputReaderPolicyInterface::ROTATION_180: {
@@ -1454,7 +1454,7 @@
         }
         case InputReaderPolicyInterface::ROTATION_270: {
             float xTemp = x;
-            x = mDisplayWidth - y;
+            x = mDisplayHeight - y;
             y = xTemp;
             break;
         }
@@ -1510,7 +1510,7 @@
 
     uint32_t fields = device->trackball.accumulator.fields;
     bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
-    bool deltaChanged = (fields & DELTA_FIELDS) == DELTA_FIELDS;
+    bool deltaChanged = fields & DELTA_FIELDS;
 
     bool down;
     if (downChanged) {
@@ -1546,10 +1546,10 @@
 
     int32_t pointerId = 0;
     PointerCoords pointerCoords;
-    pointerCoords.x = device->trackball.accumulator.relX
-            * device->trackball.precalculated.xScale;
-    pointerCoords.y = device->trackball.accumulator.relY
-            * device->trackball.precalculated.yScale;
+    pointerCoords.x = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_X
+            ? device->trackball.accumulator.relX * device->trackball.precalculated.xScale : 0;
+    pointerCoords.y = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_Y
+            ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
     pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
     pointerCoords.size = 0;