diff options
-rw-r--r-- | include/androidfw/Input.h | 9 | ||||
-rw-r--r-- | services/input/InputDispatcher.cpp | 129 | ||||
-rw-r--r-- | services/input/InputDispatcher.h | 18 | ||||
-rw-r--r-- | services/input/InputListener.cpp | 7 | ||||
-rw-r--r-- | services/input/InputListener.h | 3 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 219 | ||||
-rw-r--r-- | services/input/InputReader.h | 54 | ||||
-rw-r--r-- | services/input/InputWindow.h | 1 | ||||
-rw-r--r-- | services/input/tests/InputReader_test.cpp | 3 | ||||
-rw-r--r-- | services/java/com/android/server/display/DisplayDevice.java | 6 | ||||
-rw-r--r-- | services/java/com/android/server/display/DisplayViewport.java | 10 | ||||
-rw-r--r-- | services/java/com/android/server/input/InputManagerService.java | 6 | ||||
-rw-r--r-- | services/java/com/android/server/wm/InputMonitor.java | 16 | ||||
-rwxr-xr-x | services/java/com/android/server/wm/WindowManagerService.java | 2 | ||||
-rw-r--r-- | services/jni/com_android_server_input_InputManagerService.cpp | 7 | ||||
-rw-r--r-- | services/jni/com_android_server_input_InputWindowHandle.cpp | 6 |
16 files changed, 352 insertions, 144 deletions
diff --git a/include/androidfw/Input.h b/include/androidfw/Input.h index 2c91fab..e88835e 100644 --- a/include/androidfw/Input.h +++ b/include/androidfw/Input.h @@ -49,6 +49,15 @@ enum { }; enum { + /* Used when a motion event is not associated with any display. + * Typically used for non-pointer events. */ + ADISPLAY_ID_NONE = -1, + + /* The default display id. */ + ADISPLAY_ID_DEFAULT = 0, +}; + +enum { /* * Indicates that an input device has switches. * This input source flag is hidden from the API because switches are only used by the system diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 8604f95..87a6c1b 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -166,6 +166,10 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount, return true; } +static bool isMainDisplay(int32_t displayId) { + return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE; +} + static void dumpRegion(String8& dump, const SkRegion& region) { if (region.isEmpty()) { dump.append("<empty>"); @@ -423,11 +427,12 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplicationHandle != NULL) { + int32_t displayId = motionEntry->displayId; int32_t x = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_Y)); - sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y); + sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (touchedWindowHandle != NULL && touchedWindowHandle->inputApplicationHandle != mInputTargetWaitApplicationHandle) { @@ -444,28 +449,31 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { return needWake; } -sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) { +sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, + int32_t x, int32_t y) { // Traverse windows from front to back to find touched window. size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - int32_t flags = windowInfo->layoutParamsFlags; - - if (windowInfo->visible) { - if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { - bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE - | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; - if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { - // Found window. - return windowHandle; + if (windowInfo->displayId == displayId) { + int32_t flags = windowInfo->layoutParamsFlags; + + if (windowInfo->visible) { + if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { + bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE + | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; + if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { + // Found window. + return windowHandle; + } } } - } - if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { - // Error window is on top but not visible, so touch is dropped. - return NULL; + if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { + // Error window is on top but not visible, so touch is dropped. + return NULL; + } } } return NULL; @@ -826,7 +834,10 @@ bool InputDispatcher::dispatchMotionLocked( return true; } - addMonitoringTargetsLocked(inputTargets); + // TODO: support sending secondary display events to input monitors + if (isMainDisplay(entry->displayId)) { + addMonitoringTargetsLocked(inputTargets); + } // Dispatch the motion. if (conflictingPointerActions) { @@ -1117,6 +1128,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE; + int32_t displayId = entry->displayId; int32_t action = entry->action; int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK; @@ -1126,9 +1138,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, sp<InputWindowHandle> newHoverWindowHandle; bool isSplit = mTouchState.split; - bool switchedDevice = mTouchState.deviceId >= 0 + bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0 && (mTouchState.deviceId != entry->deviceId - || mTouchState.source != entry->source); + || mTouchState.source != entry->source + || mTouchState.displayId != displayId); bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT); @@ -1152,6 +1165,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, mTempTouchState.down = down; mTempTouchState.deviceId = entry->deviceId; mTempTouchState.source = entry->source; + mTempTouchState.displayId = displayId; isSplit = false; } else { mTempTouchState.copyFrom(mTouchState); @@ -1174,8 +1188,11 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - int32_t flags = windowInfo->layoutParamsFlags; + if (windowInfo->displayId != displayId) { + continue; // wrong display + } + int32_t flags = windowInfo->layoutParamsFlags; if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { if (topErrorWindowHandle == NULL) { topErrorWindowHandle = windowHandle; @@ -1300,7 +1317,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, sp<InputWindowHandle> oldTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle(); - sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(x, y); + sp<InputWindowHandle> newTouchedWindowHandle = + findTouchedWindowAtLocked(displayId, x, y); if (oldTouchedWindowHandle != newTouchedWindowHandle && newTouchedWindowHandle != NULL) { #if DEBUG_FOCUS @@ -1438,8 +1456,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, if (foregroundWindowHandle->getInfo()->hasWallpaper) { for (size_t i = 0; i < mWindowHandles.size(); i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); - if (windowHandle->getInfo()->layoutParamsType - == InputWindowInfo::TYPE_WALLPAPER) { + const InputWindowInfo* info = windowHandle->getInfo(); + if (info->displayId == displayId + && windowHandle->getInfo()->layoutParamsType + == InputWindowInfo::TYPE_WALLPAPER) { mTempTouchState.addOrUpdateWindow(windowHandle, InputTarget::FLAG_WINDOW_IS_OBSCURED | InputTarget::FLAG_DISPATCH_AS_IS, @@ -1495,6 +1515,7 @@ Failed: || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { mTouchState.deviceId = entry->deviceId; mTouchState.source = entry->source; + mTouchState.displayId = displayId; } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { @@ -1610,6 +1631,7 @@ bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& wind bool InputDispatcher::isWindowObscuredAtPointLocked( const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { + int32_t displayId = windowHandle->getInfo()->displayId; size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i); @@ -1618,7 +1640,8 @@ bool InputDispatcher::isWindowObscuredAtPointLocked( } const InputWindowInfo* otherInfo = otherHandle->getInfo(); - if (otherInfo->visible && ! otherInfo->isTrustedOverlay() + if (otherInfo->displayId == displayId + && otherInfo->visible && !otherInfo->isTrustedOverlay() && otherInfo->frameContainsPoint(x, y)) { return true; } @@ -1845,7 +1868,7 @@ void InputDispatcher::enqueueDispatchEntryLocked( } if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE && !connection->inputState.isHovering( - motionEntry->deviceId, motionEntry->source)) { + motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) { #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event", connection->getInputChannelName()); @@ -2271,6 +2294,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet originalMotionEntry->xPrecision, originalMotionEntry->yPrecision, originalMotionEntry->downTime, + originalMotionEntry->displayId, splitPointerCount, splitPointerProperties, splitPointerCoords); if (originalMotionEntry->injectionState) { @@ -2351,7 +2375,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { { // acquire lock mLock.lock(); - if (mInputFilterEnabled) { + if (shouldSendKeyToInputFilterLocked(args)) { mLock.unlock(); policyFlags |= POLICY_FLAG_FILTERED; @@ -2377,6 +2401,10 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { } } +bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) { + return mInputFilterEnabled; +} + void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " @@ -2415,7 +2443,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { { // acquire lock mLock.lock(); - if (mInputFilterEnabled) { + if (shouldSendMotionToInputFilterLocked(args)) { mLock.unlock(); MotionEvent event; @@ -2438,6 +2466,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { args->deviceId, args->source, policyFlags, args->action, args->flags, args->metaState, args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, + args->displayId, args->pointerCount, args->pointerProperties, args->pointerCoords); needWake = enqueueInboundEventLocked(newEntry); @@ -2449,6 +2478,11 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { } } +bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { + // TODO: support sending secondary display events to input filter + return mInputFilterEnabled && isMainDisplay(args->displayId); +} + void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchCode=%d, switchValue=%d", @@ -2532,6 +2566,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, 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(); @@ -2553,8 +2588,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), uint32_t(pointerCount), - pointerProperties, samplePointerCoords); + motionEvent->getDownTime(), displayId, + uint32_t(pointerCount), pointerProperties, samplePointerCoords); lastInjectedEntry = firstInjectedEntry; for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { sampleEventTimes += 1; @@ -2565,8 +2600,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), uint32_t(pointerCount), - pointerProperties, samplePointerCoords); + motionEvent->getDownTime(), displayId, + uint32_t(pointerCount), pointerProperties, samplePointerCoords); lastInjectedEntry->next = nextInjectedEntry; lastInjectedEntry = nextInjectedEntry; } @@ -2939,6 +2974,12 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, #endif return true; } + if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) { +#if DEBUG_FOCUS + ALOGD("Cannot transfer focus because windows are on different displays."); +#endif + return false; + } bool found = false; for (size_t i = 0; i < mTouchState.windows.size(); i++) { @@ -3040,6 +3081,7 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { 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++) { @@ -3059,11 +3101,12 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, " + dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, " + "paused=%s, hasFocus=%s, hasWallpaper=%s, " "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, " "frame=[%d,%d][%d,%d], scale=%f, " "touchableRegion=", - i, windowInfo->name.string(), + i, windowInfo->name.string(), windowInfo->displayId, toString(windowInfo->paused), toString(windowInfo->hasFocus), toString(windowInfo->hasWallpaper), @@ -3802,14 +3845,14 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, + nsecs_t downTime, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) : EventEntry(TYPE_MOTION, eventTime, policyFlags), eventTime(eventTime), deviceId(deviceId), source(source), action(action), flags(flags), metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags), xPrecision(xPrecision), yPrecision(yPrecision), - downTime(downTime), pointerCount(pointerCount) { + downTime(downTime), displayId(displayId), pointerCount(pointerCount) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); this->pointerCoords[i].copyFrom(pointerCoords[i]); @@ -3820,8 +3863,8 @@ InputDispatcher::MotionEntry::~MotionEntry() { } void InputDispatcher::MotionEntry::appendDescription(String8& msg) const { - msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x)", - action, deviceId, source); + msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)", + action, deviceId, source, displayId); } @@ -3864,11 +3907,13 @@ bool InputDispatcher::InputState::isNeutral() const { return mKeyMementos.isEmpty() && mMotionMementos.isEmpty(); } -bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source) const { +bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source, + int32_t displayId) const { for (size_t i = 0; i < mMotionMementos.size(); i++) { const MotionMemento& memento = mMotionMementos.itemAt(i); if (memento.deviceId == deviceId && memento.source == source + && memento.displayId == displayId && memento.hovering) { return true; } @@ -4025,6 +4070,7 @@ ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry, const MotionMemento& memento = mMotionMementos.itemAt(i); if (memento.deviceId == entry->deviceId && memento.source == entry->source + && memento.displayId == entry->displayId && memento.hovering == hovering) { return i; } @@ -4055,6 +4101,7 @@ void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, memento.xPrecision = entry->xPrecision; memento.yPrecision = entry->yPrecision; memento.downTime = entry->downTime; + memento.displayId = entry->displayId; memento.setPointers(entry); memento.hovering = hovering; memento.policyFlags = entry->policyFlags; @@ -4090,6 +4137,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim : AMOTION_EVENT_ACTION_CANCEL, memento.flags, 0, 0, 0, memento.xPrecision, memento.yPrecision, memento.downTime, + memento.displayId, memento.pointerCount, memento.pointerProperties, memento.pointerCoords)); } } @@ -4108,7 +4156,8 @@ void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const { for (size_t j = 0; j < other.mMotionMementos.size(); ) { const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j); if (memento.deviceId == otherMemento.deviceId - && memento.source == otherMemento.source) { + && memento.source == otherMemento.source + && memento.displayId == otherMemento.displayId) { other.mMotionMementos.removeAt(j); } else { j += 1; @@ -4240,7 +4289,7 @@ InputDispatcher::CommandEntry::~CommandEntry() { // --- InputDispatcher::TouchState --- InputDispatcher::TouchState::TouchState() : - down(false), split(false), deviceId(-1), source(0) { + down(false), split(false), deviceId(-1), source(0), displayId(-1) { } InputDispatcher::TouchState::~TouchState() { @@ -4251,6 +4300,7 @@ void InputDispatcher::TouchState::reset() { split = false; deviceId = -1; source = 0; + displayId = -1; windows.clear(); } @@ -4259,6 +4309,7 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) { split = other.split; deviceId = other.deviceId; source = other.source; + displayId = other.displayId; windows = other.windows; } diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index d0824fc..af7ff5e 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -511,15 +511,17 @@ private: float xPrecision; float yPrecision; nsecs_t downTime; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; MotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, - int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, + int32_t deviceId, uint32_t source, uint32_t policyFlags, + int32_t action, int32_t flags, + int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, + nsecs_t downTime, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); virtual void appendDescription(String8& msg) const; @@ -696,7 +698,7 @@ private: // Returns true if the specified source is known to have received a hover enter // motion event. - bool isHovering(int32_t deviceId, uint32_t source) const; + bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const; // Records tracking information for a key event that has just been published. // Returns true if the event should be delivered, false if it is inconsistent @@ -752,6 +754,7 @@ private: float xPrecision; float yPrecision; nsecs_t downTime; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; @@ -867,7 +870,7 @@ private: // to transfer focus to a new application. EventEntry* mNextUnblockedEvent; - sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t x, int32_t y); + sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y); // All registered connections mapped by channel file descriptor. KeyedVector<int, sp<Connection> > mConnectionsByFd; @@ -899,6 +902,10 @@ private: bool runCommandsLockedInterruptible(); CommandEntry* postCommandLocked(Command command); + // Input filter processing. + bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args); + bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args); + // Inbound event processing. void drainInboundQueueLocked(); void releasePendingEventLocked(); @@ -928,6 +935,7 @@ private: bool split; int32_t deviceId; // id of the device that is currently down, others are rejected uint32_t source; // source of the device that is current down, others are rejected + int32_t displayId; // id to the display that currently has a touch, others are rejected Vector<TouchedWindow> windows; TouchState(); diff --git a/services/input/InputListener.cpp b/services/input/InputListener.cpp index 657a6b9..c2705b0 100644 --- a/services/input/InputListener.cpp +++ b/services/input/InputListener.cpp @@ -69,12 +69,12 @@ void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const { NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, uint32_t pointerCount, + int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime) : eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags), action(action), flags(flags), metaState(metaState), buttonState(buttonState), - edgeFlags(edgeFlags), pointerCount(pointerCount), + edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount), xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); @@ -87,7 +87,8 @@ NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) : policyFlags(other.policyFlags), action(other.action), flags(other.flags), metaState(other.metaState), buttonState(other.buttonState), - edgeFlags(other.edgeFlags), pointerCount(other.pointerCount), + edgeFlags(other.edgeFlags), displayId(other.displayId), + pointerCount(other.pointerCount), xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) { for (uint32_t i = 0; i < pointerCount; i++) { pointerProperties[i].copyFrom(other.pointerProperties[i]); diff --git a/services/input/InputListener.h b/services/input/InputListener.h index b1dc0b8..486852b 100644 --- a/services/input/InputListener.h +++ b/services/input/InputListener.h @@ -88,6 +88,7 @@ struct NotifyMotionArgs : public NotifyArgs { int32_t metaState; int32_t buttonState; int32_t edgeFlags; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; @@ -99,7 +100,7 @@ struct NotifyMotionArgs : public NotifyArgs { NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, uint32_t pointerCount, + int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime); diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 513dc13..d56b9a9 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -2431,6 +2431,7 @@ void CursorInputMapper::sync(nsecs_t when) { mPointerVelocityControl.move(when, &deltaX, &deltaY); + int32_t displayId; if (mPointerController != NULL) { if (moved || scrolled || buttonsChanged) { mPointerController->setPresentation( @@ -2451,9 +2452,11 @@ void CursorInputMapper::sync(nsecs_t when) { mPointerController->getPosition(&x, &y); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); + displayId = ADISPLAY_ID_DEFAULT; } else { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); + displayId = ADISPLAY_ID_NONE; } pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); @@ -2485,7 +2488,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, motionEventAction, 0, metaState, currentButtonState, 0, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&args); // Send hover move after UP to tell the application that the mouse is hovering now. @@ -2494,7 +2498,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&hoverArgs); } @@ -2506,7 +2511,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&scrollArgs); } } @@ -2539,7 +2545,8 @@ void CursorInputMapper::fadePointer() { TouchInputMapper::TouchInputMapper(InputDevice* device) : InputMapper(device), mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), - mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) { + mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), + mSurfaceOrientation(DISPLAY_ORIENTATION_0) { } TouchInputMapper::~TouchInputMapper() { @@ -2601,6 +2608,8 @@ void TouchInputMapper::dump(String8& dump) { dumpSurface(dump); dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); + dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate); + dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate); dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale); dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale); dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision); @@ -2810,7 +2819,7 @@ void TouchInputMapper::dumpParameters(String8& dump) { ALOG_ASSERT(false); } - dump.appendFormat(INDENT4 "AssociatedDisplay: present=%s, isExternal=%s\n", + dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n", toString(mParameters.hasAssociatedDisplay), toString(mParameters.associatedDisplayIsExternal)); dump.appendFormat(INDENT4 "OrientationAware: %s\n", @@ -2869,10 +2878,15 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { return; } + // Raw width and height in the natural orientation. + int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; + int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; + // Get associated display dimensions. + bool viewportChanged = false; + DisplayViewport newViewport; if (mParameters.hasAssociatedDisplay) { - if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, - &mAssociatedDisplayViewport)) { + if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) { ALOGI(INDENT "Touch device '%s' could not query the properties of its associated " "display. The device will be inoperable until the display size " "becomes available.", @@ -2880,25 +2894,77 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mDeviceMode = DEVICE_MODE_DISABLED; return; } - } + } else { + newViewport.setNonDisplayViewport(rawWidth, rawHeight); + } + if (mViewport != newViewport) { + mViewport = newViewport; + viewportChanged = true; + + if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { + // Convert rotated viewport to natural surface coordinates. + int32_t naturalLogicalWidth, naturalLogicalHeight; + int32_t naturalPhysicalWidth, naturalPhysicalHeight; + int32_t naturalPhysicalLeft, naturalPhysicalTop; + int32_t naturalDeviceWidth, naturalDeviceHeight; + switch (mViewport.orientation) { + case DISPLAY_ORIENTATION_90: + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom; + naturalPhysicalTop = mViewport.physicalLeft; + naturalDeviceWidth = mViewport.deviceHeight; + naturalDeviceHeight = mViewport.deviceWidth; + break; + case DISPLAY_ORIENTATION_180: + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight; + naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom; + naturalDeviceWidth = mViewport.deviceWidth; + naturalDeviceHeight = mViewport.deviceHeight; + break; + case DISPLAY_ORIENTATION_270: + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalLeft = mViewport.physicalTop; + naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight; + naturalDeviceWidth = mViewport.deviceHeight; + naturalDeviceHeight = mViewport.deviceWidth; + break; + case DISPLAY_ORIENTATION_0: + default: + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalLeft = mViewport.physicalLeft; + naturalPhysicalTop = mViewport.physicalTop; + naturalDeviceWidth = mViewport.deviceWidth; + naturalDeviceHeight = mViewport.deviceHeight; + break; + } + + mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; + mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; + mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; + mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; - // Configure dimensions. - int32_t width, height, orientation; - if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { - width = mAssociatedDisplayViewport.logicalRight - mAssociatedDisplayViewport.logicalLeft; - height = mAssociatedDisplayViewport.logicalBottom - mAssociatedDisplayViewport.logicalTop; - if (mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_90 - || mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_270) { - int32_t temp = height; - height = width; - width = temp; + mSurfaceOrientation = mParameters.orientationAware ? + mViewport.orientation : DISPLAY_ORIENTATION_0; + } else { + mSurfaceWidth = rawWidth; + mSurfaceHeight = rawHeight; + mSurfaceLeft = 0; + mSurfaceTop = 0; + mSurfaceOrientation = DISPLAY_ORIENTATION_0; } - orientation = mParameters.orientationAware ? - mAssociatedDisplayViewport.orientation : DISPLAY_ORIENTATION_0; - } else { - width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; - orientation = DISPLAY_ORIENTATION_0; } // If moving between pointer modes, need to reset some state. @@ -2918,22 +2984,17 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPointerController.clear(); } - bool orientationChanged = mSurfaceOrientation != orientation; - if (orientationChanged) { - mSurfaceOrientation = orientation; - } - - bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height; - if (sizeChanged || deviceModeChanged) { - ALOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d, mode is %d", - getDeviceId(), getDeviceName().string(), width, height, mDeviceMode); - - mSurfaceWidth = width; - mSurfaceHeight = height; + if (viewportChanged || deviceModeChanged) { + ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, " + "display id %d", + getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight, + mSurfaceOrientation, mDeviceMode, mViewport.displayId); // Configure X and Y factors. - mXScale = float(width) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1); - mYScale = float(height) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1); + mXScale = float(mSurfaceWidth) / rawWidth; + mYScale = float(mSurfaceHeight) / rawHeight; + mXTranslate = -mSurfaceLeft; + mYTranslate = -mSurfaceTop; mXPrecision = 1.0f / mXScale; mYPrecision = 1.0f / mYScale; @@ -2950,7 +3011,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mGeometricScale = avg(mXScale, mYScale); // Size of diagonal axis. - float diagonalSize = hypotf(width, height); + float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight); // Size factors. if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { @@ -3102,50 +3163,38 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mOrientedRanges.distance.fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale; } - } - if (orientationChanged || sizeChanged || deviceModeChanged) { - // Compute oriented surface dimensions, precision, scales and ranges. + // Compute oriented precision, scales and ranges. // Note that the maximum value reported is an inclusive maximum value so it is one // unit less than the total width or height of surface. switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: case DISPLAY_ORIENTATION_270: - mOrientedSurfaceWidth = mSurfaceHeight; - mOrientedSurfaceHeight = mSurfaceWidth; - mOrientedXPrecision = mYPrecision; mOrientedYPrecision = mXPrecision; - mOrientedRanges.x.min = 0; - mOrientedRanges.x.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) - * mYScale; + mOrientedRanges.x.min = mYTranslate; + mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = mYScale; - mOrientedRanges.y.min = 0; - mOrientedRanges.y.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) - * mXScale; + mOrientedRanges.y.min = mXTranslate; + mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = mXScale; break; default: - mOrientedSurfaceWidth = mSurfaceWidth; - mOrientedSurfaceHeight = mSurfaceHeight; - mOrientedXPrecision = mXPrecision; mOrientedYPrecision = mYPrecision; - mOrientedRanges.x.min = 0; - mOrientedRanges.x.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) - * mXScale; + mOrientedRanges.x.min = mXTranslate; + mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = mXScale; - mOrientedRanges.y.min = 0; - mOrientedRanges.y.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) - * mYScale; + mOrientedRanges.y.min = mYTranslate; + mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = mYScale; break; @@ -3153,10 +3202,8 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // Compute pointer gesture detection parameters. if (mDeviceMode == DEVICE_MODE_POINTER) { - int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; float rawDiagonal = hypotf(rawWidth, rawHeight); - float displayDiagonal = hypotf(width, height); + float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight); // Scale movements such that one whole swipe of the touch pad covers a // given area relative to the diagonal size of the display when no acceleration @@ -3191,8 +3238,21 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { } void TouchInputMapper::dumpSurface(String8& dump) { + dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, " + "logicalFrame=[%d, %d, %d, %d], " + "physicalFrame=[%d, %d, %d, %d], " + "deviceSize=[%d, %d]\n", + mViewport.displayId, mViewport.orientation, + mViewport.logicalLeft, mViewport.logicalTop, + mViewport.logicalRight, mViewport.logicalBottom, + mViewport.physicalLeft, mViewport.physicalTop, + mViewport.physicalRight, mViewport.physicalBottom, + mViewport.deviceWidth, mViewport.deviceHeight); + dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth); dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); + dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); + dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); } @@ -4087,28 +4147,28 @@ void TouchInputMapper::cookPointerData() { float x, y; switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: - x = float(in.y - mRawPointerAxes.y.minValue) * mYScale; - y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; + x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; + y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; orientation -= M_PI_2; if (orientation < - M_PI_2) { orientation += M_PI; } break; case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; - y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; + x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; + y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; break; case DISPLAY_ORIENTATION_270: - x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; - y = float(in.x - mRawPointerAxes.x.minValue) * mXScale; + x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; + y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; orientation += M_PI_2; if (orientation > M_PI_2) { orientation -= M_PI; } break; default: - x = float(in.x - mRawPointerAxes.x.minValue) * mXScale; - y = float(in.y - mRawPointerAxes.y.minValue) * mYScale; + x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; + y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; break; } @@ -4364,7 +4424,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime); + mViewport.displayId, 1, &pointerProperties, &pointerCoords, + 0, 0, mPointerGesture.downTime); getListener()->notifyMotion(&args); } @@ -5272,6 +5333,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send up. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5284,6 +5346,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover exit. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5298,6 +5361,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send down. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5307,6 +5371,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send move. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5320,6 +5385,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover enter. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5329,6 +5395,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover move. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5349,6 +5416,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &pointerCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5410,7 +5478,8 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, action, flags, metaState, buttonState, edgeFlags, - pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime); + mViewport.displayId, pointerCount, pointerProperties, pointerCoords, + xPrecision, yPrecision, downTime); getListener()->notifyMotion(&args); } @@ -6213,7 +6282,7 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { } } - // Moving a joystick axis should not wake the devide because joysticks can + // Moving a joystick axis should not wake the device because joysticks can // be fairly noisy even when not in use. On the other hand, pushing a gamepad // button will likely wake the device. // TODO: Use the input device configuration to control this behavior more finely. @@ -6221,7 +6290,7 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, 0, 0, 0); + ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0); getListener()->notifyMotion(&args); } diff --git a/services/input/InputReader.h b/services/input/InputReader.h index e345a5f..e1a8dd8 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -62,11 +62,14 @@ struct DisplayViewport { int32_t physicalTop; int32_t physicalRight; int32_t physicalBottom; + int32_t deviceWidth; + int32_t deviceHeight; DisplayViewport() : - displayId(-1), orientation(DISPLAY_ORIENTATION_0), + displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0), logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0), - physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0) { + physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0), + deviceWidth(0), deviceHeight(0) { } bool operator==(const DisplayViewport& other) const { @@ -79,12 +82,33 @@ struct DisplayViewport { && physicalLeft == other.physicalLeft && physicalTop == other.physicalTop && physicalRight == other.physicalRight - && physicalBottom == other.physicalBottom; + && physicalBottom == other.physicalBottom + && deviceWidth == other.deviceWidth + && deviceHeight == other.deviceHeight; } bool operator!=(const DisplayViewport& other) const { return !(*this == other); } + + inline bool isValid() const { + return displayId >= 0; + } + + void setNonDisplayViewport(int32_t width, int32_t height) { + displayId = ADISPLAY_ID_NONE; + orientation = DISPLAY_ORIENTATION_0; + logicalLeft = 0; + logicalTop = 0; + logicalRight = width; + logicalBottom = height; + physicalLeft = 0; + physicalTop = 0; + physicalRight = width; + physicalBottom = height; + deviceWidth = width; + deviceHeight = height; + } }; /* @@ -1297,18 +1321,30 @@ protected: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0; private: - // The surface orientation and width and height set by configureSurface(). - int32_t mSurfaceOrientation; + // The current viewport. + // The components of the viewport are specified in the display's rotated orientation. + DisplayViewport mViewport; + + // The surface orientation, width and height set by configureSurface(). + // The width and height are derived from the viewport but are specified + // in the natural orientation. + // The surface origin specifies how the surface coordinates should be translated + // to align with the logical display coordinate space. + // The orientation may be different from the viewport orientation as it specifies + // the rotation of the surface coordinates required to produce the viewport's + // requested orientation, so it will depend on whether the device is orientation aware. int32_t mSurfaceWidth; int32_t mSurfaceHeight; - - // The associated display viewport set by configureSurface(). - DisplayViewport mAssociatedDisplayViewport; + int32_t mSurfaceLeft; + int32_t mSurfaceTop; + int32_t mSurfaceOrientation; // Translation and scaling factors, orientation-independent. + float mXTranslate; float mXScale; float mXPrecision; + float mYTranslate; float mYScale; float mYPrecision; @@ -1369,8 +1405,6 @@ private: } mOrientedRanges; // Oriented dimensions and precision. - float mOrientedSurfaceWidth; - float mOrientedSurfaceHeight; float mOrientedXPrecision; float mOrientedYPrecision; diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h index 824a64b..3118099 100644 --- a/services/input/InputWindow.h +++ b/services/input/InputWindow.h @@ -132,6 +132,7 @@ struct InputWindowInfo { int32_t ownerPid; int32_t ownerUid; int32_t inputFeatures; + int32_t displayId; bool touchableRegionContainsPoint(int32_t x, int32_t y) const; bool frameContainsPoint(int32_t x, int32_t y) const; diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 03516af..c6dbbf3 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -151,6 +151,8 @@ public: v.physicalTop = 0; v.physicalRight = isRotated ? height : width; v.physicalBottom = isRotated ? width : height; + v.deviceWidth = isRotated ? height : width; + v.deviceHeight = isRotated ? width : height; mConfig.setDisplayInfo(false /*external*/, v); mConfig.setDisplayInfo(true /*external*/, v); } @@ -487,6 +489,7 @@ private: return OK; } } + outAxisInfo->clear(); return -1; } diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java index 8eeefb4..f5aa3d4 100644 --- a/services/java/com/android/server/display/DisplayDevice.java +++ b/services/java/com/android/server/display/DisplayDevice.java @@ -176,6 +176,12 @@ abstract class DisplayDevice { } else { viewport.physicalFrame.setEmpty(); } + + boolean isRotated = (mCurrentOrientation == Surface.ROTATION_90 + || mCurrentOrientation == Surface.ROTATION_270); + DisplayDeviceInfo info = getDisplayDeviceInfoLocked(); + viewport.deviceWidth = isRotated ? info.height : info.width; + viewport.deviceHeight = isRotated ? info.width : info.height; } /** diff --git a/services/java/com/android/server/display/DisplayViewport.java b/services/java/com/android/server/display/DisplayViewport.java index ed4016d..5080556 100644 --- a/services/java/com/android/server/display/DisplayViewport.java +++ b/services/java/com/android/server/display/DisplayViewport.java @@ -44,12 +44,20 @@ public final class DisplayViewport { // should be scaled or translated after rotation. public final Rect physicalFrame = new Rect(); + // The full width and height of the display device, rotated in the same + // manner as physicalFrame. This expresses the full native size of the display device. + // The physical frame should usually fit within this area. + public int deviceWidth; + public int deviceHeight; + public void copyFrom(DisplayViewport viewport) { valid = viewport.valid; displayId = viewport.displayId; orientation = viewport.orientation; logicalFrame.set(viewport.logicalFrame); physicalFrame.set(viewport.physicalFrame); + deviceWidth = viewport.deviceWidth; + deviceHeight = viewport.deviceHeight; } // For debugging purposes. @@ -60,6 +68,8 @@ public final class DisplayViewport { + ", orientation=" + orientation + ", logicalFrame=" + logicalFrame + ", physicalFrame=" + physicalFrame + + ", deviceWidth=" + deviceWidth + + ", deviceHeight=" + deviceHeight + "}"; } } diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index 95655a5..805818a 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -149,7 +149,8 @@ public class InputManagerService extends IInputManager.Stub private static native void nativeSetDisplayViewport(int ptr, boolean external, int displayId, int rotation, int logicalLeft, int logicalTop, int logicalRight, int logicalBottom, - int physicalLeft, int physicalTop, int physicalRight, int physicalBottom); + int physicalLeft, int physicalTop, int physicalRight, int physicalBottom, + int deviceWidth, int deviceHeight); private static native int nativeGetScanCodeState(int ptr, int deviceId, int sourceMask, int scanCode); @@ -305,7 +306,8 @@ public class InputManagerService extends IInputManager.Stub viewport.logicalFrame.left, viewport.logicalFrame.top, viewport.logicalFrame.right, viewport.logicalFrame.bottom, viewport.physicalFrame.left, viewport.physicalFrame.top, - viewport.physicalFrame.right, viewport.physicalFrame.bottom); + viewport.physicalFrame.right, viewport.physicalFrame.bottom, + viewport.deviceWidth, viewport.deviceHeight); } /** diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 5ff8a9b..aa18ee4 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -19,11 +19,13 @@ package com.android.server.wm; import com.android.server.input.InputManagerService; import com.android.server.input.InputApplicationHandle; import com.android.server.input.InputWindowHandle; +import com.android.server.wm.WindowManagerService.AllWindowsIterator; import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; import android.util.Slog; +import android.view.Display; import android.view.InputChannel; import android.view.KeyEvent; import android.view.WindowManager; @@ -225,10 +227,11 @@ final class InputMonitor implements InputManagerService.Callbacks { addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle); } - // TODO(multidisplay): Input only occurs on the default display. - final WindowList windows = mService.getDefaultWindowList(); - for (int i = windows.size() - 1; i >= 0; i--) { - final WindowState child = windows.get(i); + // Add all windows on the default display. + final AllWindowsIterator iterator = mService.new AllWindowsIterator( + WindowManagerService.REVERSE_ITERATOR); + while (iterator.hasNext()) { + final WindowState child = iterator.next(); final InputChannel inputChannel = child.mInputChannel; final InputWindowHandle inputWindowHandle = child.mInputWindowHandle; if (inputChannel == null || inputWindowHandle == null || child.mRemoved) { @@ -243,15 +246,16 @@ final class InputMonitor implements InputManagerService.Callbacks { final boolean isVisible = child.isVisibleLw(); final boolean hasWallpaper = (child == mService.mWallpaperTarget) && (type != WindowManager.LayoutParams.TYPE_KEYGUARD); + final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY); // If there's a drag in progress and 'child' is a potential drop target, // make sure it's been told about the drag - if (inDrag && isVisible) { + if (inDrag && isVisible && onDefaultDisplay) { mService.mDragState.sendDragStartedIfNeededLw(child); } if (universeBackground != null && !addedUniverse - && child.mBaseLayer < aboveUniverseLayer) { + && child.mBaseLayer < aboveUniverseLayer && onDefaultDisplay) { final WindowState u = universeBackground.mWin; if (u.mInputChannel != null && u.mInputWindowHandle != null) { addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags, diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index cdca8bc..a7ea01d 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -10744,7 +10744,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - boolean REVERSE_ITERATOR = true; + final static boolean REVERSE_ITERATOR = true; class AllWindowsIterator implements Iterator<WindowState> { private DisplayContent mDisplayContent; private DisplayContentsIterator mDisplayContentsIterator; diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp index 5e36bf8..319cacd 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/jni/com_android_server_input_InputManagerService.cpp @@ -993,7 +993,8 @@ static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) { static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboolean external, jint displayId, jint orientation, jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom, - jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom) { + jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom, + jint deviceWidth, jint deviceHeight) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); DisplayViewport v; @@ -1007,6 +1008,8 @@ static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboole v.physicalTop = physicalTop; v.physicalRight = physicalRight; v.physicalBottom = physicalBottom; + v.deviceWidth = deviceWidth; + v.deviceHeight = deviceHeight; im->setDisplayViewport(external, v); } @@ -1288,7 +1291,7 @@ static JNINativeMethod gInputManagerMethods[] = { (void*) nativeInit }, { "nativeStart", "(I)V", (void*) nativeStart }, - { "nativeSetDisplayViewport", "(IZIIIIIIIIII)V", + { "nativeSetDisplayViewport", "(IZIIIIIIIIIIII)V", (void*) nativeSetDisplayViewport }, { "nativeGetScanCodeState", "(IIII)I", (void*) nativeGetScanCodeState }, diff --git a/services/jni/com_android_server_input_InputWindowHandle.cpp b/services/jni/com_android_server_input_InputWindowHandle.cpp index 01fb781..6692994 100644 --- a/services/jni/com_android_server_input_InputWindowHandle.cpp +++ b/services/jni/com_android_server_input_InputWindowHandle.cpp @@ -52,6 +52,7 @@ static struct { jfieldID ownerPid; jfieldID ownerUid; jfieldID inputFeatures; + jfieldID displayId; } gInputWindowHandleClassInfo; static Mutex gHandleMutex; @@ -151,6 +152,8 @@ bool NativeInputWindowHandle::updateInfo() { gInputWindowHandleClassInfo.ownerUid); mInfo->inputFeatures = env->GetIntField(obj, gInputWindowHandleClassInfo.inputFeatures); + mInfo->displayId = env->GetIntField(obj, + gInputWindowHandleClassInfo.displayId); env->DeleteLocalRef(obj); return true; @@ -291,6 +294,9 @@ int register_android_server_InputWindowHandle(JNIEnv* env) { GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz, "inputFeatures", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz, + "displayId", "I"); return 0; } |