Add support for injecting events into ActivityContainers.

Enhanced the input system to support concurrent dispatch of touch
events on multiple displays which is required for this to work.

Add method to apply offset to PointerCoords.

Change-Id: I55fe4a9a8785ae5a2d3341d214fa3c5107f3963a
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index c000460..f933681 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1023,7 +1023,14 @@
                 sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
 
                 if (windowHandle != NULL) {
-                    mTouchState.removeWindow(windowHandle);
+                    const InputWindowInfo* info = windowHandle->getInfo();
+                    if (info) {
+                        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(info->displayId);
+                        if (stateIndex >= 0) {
+                            mTouchStatesByDisplay.editValueAt(stateIndex).removeWindow(
+                                    windowHandle);
+                        }
+                    }
                 }
 
                 if (connection->status == Connection::STATUS_NORMAL) {
@@ -1164,11 +1171,21 @@
     InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
     sp<InputWindowHandle> newHoverWindowHandle;
 
-    bool isSplit = mTouchState.split;
-    bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0
-            && (mTouchState.deviceId != entry->deviceId
-                    || mTouchState.source != entry->source
-                    || mTouchState.displayId != displayId);
+    // Copy current touch state into mTempTouchState.
+    // This state is always reset at the end of this function, so if we don't find state
+    // for the specified display then our initial state will be empty.
+    const TouchState* oldState = NULL;
+    ssize_t oldStateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
+    if (oldStateIndex >= 0) {
+        oldState = &mTouchStatesByDisplay.valueAt(oldStateIndex);
+        mTempTouchState.copyFrom(*oldState);
+    }
+
+    bool isSplit = mTempTouchState.split;
+    bool switchedDevice = mTempTouchState.deviceId >= 0 && mTempTouchState.displayId >= 0
+            && (mTempTouchState.deviceId != entry->deviceId
+                    || mTempTouchState.source != entry->source
+                    || mTempTouchState.displayId != displayId);
     bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
             || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
             || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
@@ -1178,11 +1195,10 @@
     bool wrongDevice = false;
     if (newGesture) {
         bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
-        if (switchedDevice && mTouchState.down && !down) {
+        if (switchedDevice && mTempTouchState.down && !down) {
 #if DEBUG_FOCUS
             ALOGD("Dropping event because a pointer for a different device is already down.");
 #endif
-            mTempTouchState.copyFrom(mTouchState);
             injectionResult = INPUT_EVENT_INJECTION_FAILED;
             switchedDevice = false;
             wrongDevice = true;
@@ -1194,8 +1210,6 @@
         mTempTouchState.source = entry->source;
         mTempTouchState.displayId = displayId;
         isSplit = false;
-    } else {
-        mTempTouchState.copyFrom(mTouchState);
     }
 
     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
@@ -1518,32 +1532,31 @@
 
             if (isHoverAction) {
                 // Started hovering, therefore no longer down.
-                if (mTouchState.down) {
+                if (oldState && oldState->down) {
 #if DEBUG_FOCUS
                     ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
 #endif
                     *outConflictingPointerActions = true;
                 }
-                mTouchState.reset();
+                mTempTouchState.reset();
                 if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
                         || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
-                    mTouchState.deviceId = entry->deviceId;
-                    mTouchState.source = entry->source;
-                    mTouchState.displayId = displayId;
+                    mTempTouchState.deviceId = entry->deviceId;
+                    mTempTouchState.source = entry->source;
+                    mTempTouchState.displayId = displayId;
                 }
             } else if (maskedAction == AMOTION_EVENT_ACTION_UP
                     || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
                 // All pointers up or canceled.
-                mTouchState.reset();
+                mTempTouchState.reset();
             } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
                 // First pointer went down.
-                if (mTouchState.down) {
+                if (oldState && oldState->down) {
 #if DEBUG_FOCUS
                     ALOGD("Conflicting pointer actions: Down received while already down.");
 #endif
                     *outConflictingPointerActions = true;
                 }
-                mTouchState.copyFrom(mTempTouchState);
             } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
                 // One pointer went up.
                 if (isSplit) {
@@ -1562,12 +1575,20 @@
                         i += 1;
                     }
                 }
-                mTouchState.copyFrom(mTempTouchState);
-            } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
-                // Discard temporary touch state since it was only valid for this action.
-            } else {
-                // Save changes to touch state as-is for all other actions.
-                mTouchState.copyFrom(mTempTouchState);
+            }
+
+            // Save changes unless the action was scroll in which case the temporary touch
+            // state was only valid for this one action.
+            if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
+                if (mTempTouchState.displayId >= 0) {
+                    if (oldStateIndex >= 0) {
+                        mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
+                    } else {
+                        mTouchStatesByDisplay.add(displayId, mTempTouchState);
+                    }
+                } else if (oldStateIndex >= 0) {
+                    mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
+                }
             }
 
             // Update hover state.
@@ -2319,7 +2340,7 @@
             originalMotionEntry->yPrecision,
             originalMotionEntry->downTime,
             originalMotionEntry->displayId,
-            splitPointerCount, splitPointerProperties, splitPointerCoords);
+            splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
 
     if (originalMotionEntry->injectionState) {
         splitMotionEntry->injectionState = originalMotionEntry->injectionState;
@@ -2491,7 +2512,7 @@
                 args->action, args->flags, args->metaState, args->buttonState,
                 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                 args->displayId,
-                args->pointerCount, args->pointerProperties, args->pointerCoords);
+                args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
 
         needWake = enqueueInboundEventLocked(newEntry);
         mLock.unlock();
@@ -2539,7 +2560,7 @@
     }
 }
 
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
+int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displayId,
         int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
         uint32_t policyFlags) {
 #if DEBUG_INBOUND_EVENT_DETAILS
@@ -2590,7 +2611,6 @@
 
     case AINPUT_EVENT_TYPE_MOTION: {
         const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
-        int32_t displayId = ADISPLAY_ID_DEFAULT;
         int32_t action = motionEvent->getAction();
         size_t pointerCount = motionEvent->getPointerCount();
         const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
@@ -2613,7 +2633,8 @@
                 motionEvent->getEdgeFlags(),
                 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
                 motionEvent->getDownTime(), displayId,
-                uint32_t(pointerCount), pointerProperties, samplePointerCoords);
+                uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+                motionEvent->getXOffset(), motionEvent->getYOffset());
         lastInjectedEntry = firstInjectedEntry;
         for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
             sampleEventTimes += 1;
@@ -2625,7 +2646,8 @@
                     motionEvent->getEdgeFlags(),
                     motionEvent->getXPrecision(), motionEvent->getYPrecision(),
                     motionEvent->getDownTime(), displayId,
-                    uint32_t(pointerCount), pointerProperties, samplePointerCoords);
+                    uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+                    motionEvent->getXOffset(), motionEvent->getYOffset());
             lastInjectedEntry->next = nextInjectedEntry;
             lastInjectedEntry = nextInjectedEntry;
         }
@@ -2850,22 +2872,25 @@
             mFocusedWindowHandle = newFocusedWindowHandle;
         }
 
-        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
-            TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
-            if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
+        for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+            TouchState& state = mTouchStatesByDisplay.editValueAt(d);
+            for (size_t i = 0; i < state.windows.size(); i++) {
+                TouchedWindow& touchedWindow = state.windows.editItemAt(i);
+                if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
-                ALOGD("Touched window was removed: %s",
-                        touchedWindow.windowHandle->getName().string());
+                    ALOGD("Touched window was removed: %s",
+                            touchedWindow.windowHandle->getName().string());
 #endif
-                sp<InputChannel> touchedInputChannel =
-                        touchedWindow.windowHandle->getInputChannel();
-                if (touchedInputChannel != NULL) {
-                    CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
-                            "touched window was removed");
-                    synthesizeCancelationEventsForInputChannelLocked(
-                            touchedInputChannel, options);
+                    sp<InputChannel> touchedInputChannel =
+                            touchedWindow.windowHandle->getInputChannel();
+                    if (touchedInputChannel != NULL) {
+                        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+                                "touched window was removed");
+                        synthesizeCancelationEventsForInputChannelLocked(
+                                touchedInputChannel, options);
+                    }
+                    state.windows.removeAt(i--);
                 }
-                mTouchState.windows.removeAt(i--);
             }
         }
 
@@ -3006,23 +3031,27 @@
         }
 
         bool found = false;
-        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            if (touchedWindow.windowHandle == fromWindowHandle) {
-                int32_t oldTargetFlags = touchedWindow.targetFlags;
-                BitSet32 pointerIds = touchedWindow.pointerIds;
+        for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+            TouchState& state = mTouchStatesByDisplay.editValueAt(d);
+            for (size_t i = 0; i < state.windows.size(); i++) {
+                const TouchedWindow& touchedWindow = state.windows[i];
+                if (touchedWindow.windowHandle == fromWindowHandle) {
+                    int32_t oldTargetFlags = touchedWindow.targetFlags;
+                    BitSet32 pointerIds = touchedWindow.pointerIds;
 
-                mTouchState.windows.removeAt(i);
+                    state.windows.removeAt(i);
 
-                int32_t newTargetFlags = oldTargetFlags
-                        & (InputTarget::FLAG_FOREGROUND
-                                | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
-                mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
+                    int32_t newTargetFlags = oldTargetFlags
+                            & (InputTarget::FLAG_FOREGROUND
+                                    | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
+                    state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
 
-                found = true;
-                break;
+                    found = true;
+                    goto Found;
+                }
             }
         }
+Found:
 
         if (! found) {
 #if DEBUG_FOCUS
@@ -3066,7 +3095,7 @@
     drainInboundQueueLocked();
     resetANRTimeoutsLocked();
 
-    mTouchState.reset();
+    mTouchStatesByDisplay.clear();
     mLastHoverWindowHandle.clear();
 }
 
@@ -3101,22 +3130,28 @@
     dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
             mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>");
 
-    dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
-    dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
-    dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
-    dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source);
-    dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId);
-    if (!mTouchState.windows.isEmpty()) {
-        dump.append(INDENT "TouchedWindows:\n");
-        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
-                    i, touchedWindow.windowHandle->getName().string(),
-                    touchedWindow.pointerIds.value,
-                    touchedWindow.targetFlags);
+    if (!mTouchStatesByDisplay.isEmpty()) {
+        dump.appendFormat(INDENT "TouchStatesByDisplay:\n");
+        for (size_t i = 0; i < mTouchStatesByDisplay.size(); i++) {
+            const TouchState& state = mTouchStatesByDisplay.valueAt(i);
+            dump.appendFormat(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n",
+                    state.displayId, toString(state.down), toString(state.split),
+                    state.deviceId, state.source);
+            if (!state.windows.isEmpty()) {
+                dump.append(INDENT3 "Windows:\n");
+                for (size_t i = 0; i < state.windows.size(); i++) {
+                    const TouchedWindow& touchedWindow = state.windows[i];
+                    dump.appendFormat(INDENT4 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+                            i, touchedWindow.windowHandle->getName().string(),
+                            touchedWindow.pointerIds.value,
+                            touchedWindow.targetFlags);
+                }
+            } else {
+                dump.append(INDENT3 "Windows: <none>\n");
+            }
         }
     } else {
-        dump.append(INDENT "TouchedWindows: <none>\n");
+        dump.append(INDENT "TouchStates: <no displays touched>\n");
     }
 
     if (!mWindowHandles.isEmpty()) {
@@ -3901,7 +3936,8 @@
         int32_t metaState, int32_t buttonState,
         int32_t edgeFlags, float xPrecision, float yPrecision,
         nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
-        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) :
+        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+        float xOffset, float yOffset) :
         EventEntry(TYPE_MOTION, eventTime, policyFlags),
         eventTime(eventTime),
         deviceId(deviceId), source(source), action(action), flags(flags),
@@ -3911,6 +3947,9 @@
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
         this->pointerCoords[i].copyFrom(pointerCoords[i]);
+        if (xOffset || yOffset) {
+            this->pointerCoords[i].applyOffset(xOffset, yOffset);
+        }
     }
 }
 
@@ -4204,7 +4243,8 @@
                     memento.flags, 0, 0, 0,
                     memento.xPrecision, memento.yPrecision, memento.downTime,
                     memento.displayId,
-                    memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
+                    memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
+                    0, 0));
         }
     }
 }