Fix foldable emulator touch does not work
When foldable emulator change to minimized state and rotate screen,
the physical display would align to right-top (rotate to 90) or
left-bottom (rotate to 270), but the touch axes range still keep
the initialed values, so when cookPointerData, it would also align to
right-top or left-bottom when display rotated.
- Fix the surface range when display had offset and rotated.
- Fix the surface range checker function.
Bug: 138708005
Test: atest inputflinger_tests
Test: open foldable emulator, change to minimized state and rotate device,
test if touch can work fine.
Change-Id: Idc97107512dd1c11e3783eb3276635f69d3b047b
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 34603b9..c80a2dc 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -668,7 +668,7 @@
naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
+ naturalPhysicalLeft = mViewport.deviceHeight - naturalPhysicalWidth;
naturalPhysicalTop = mViewport.physicalLeft;
naturalDeviceWidth = mViewport.deviceHeight;
naturalDeviceHeight = mViewport.deviceWidth;
@@ -689,7 +689,7 @@
naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
naturalPhysicalLeft = mViewport.physicalTop;
- naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
+ naturalPhysicalTop = mViewport.deviceWidth - naturalPhysicalHeight;
naturalDeviceWidth = mViewport.deviceHeight;
naturalDeviceHeight = mViewport.deviceWidth;
break;
@@ -2173,6 +2173,7 @@
// TODO: Adjust coverage coords?
float xTransformed = in.x, yTransformed = in.y;
mAffineTransform.applyTo(xTransformed, yTransformed);
+ rotateAndScale(xTransformed, yTransformed);
// Adjust X, Y, and coverage coords for surface orientation.
float x, y;
@@ -2180,8 +2181,8 @@
switch (mSurfaceOrientation) {
case DISPLAY_ORIENTATION_90:
- x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
+ x = yTransformed + mYTranslate;
+ y = xTransformed + mXTranslate;
left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
@@ -2194,8 +2195,8 @@
}
break;
case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
- y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
+ x = xTransformed + mXTranslate;
+ y = yTransformed + mYTranslate;
left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
@@ -2208,8 +2209,8 @@
}
break;
case DISPLAY_ORIENTATION_270:
- x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
- y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ x = yTransformed + mYTranslate;
+ y = xTransformed + mXTranslate;
left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
@@ -2222,8 +2223,8 @@
}
break;
default:
- x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ x = xTransformed + mXTranslate;
+ y = yTransformed + mYTranslate;
left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
@@ -3617,13 +3618,34 @@
abortTouches(when, 0 /* policyFlags*/);
}
+void TouchInputMapper::rotateAndScale(float& x, float& y) {
+ switch (mSurfaceOrientation) {
+ case DISPLAY_ORIENTATION_90:
+ x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
+ y = float(y - mRawPointerAxes.y.minValue) * mYScale;
+ break;
+ case DISPLAY_ORIENTATION_180:
+ x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
+ y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
+ break;
+ case DISPLAY_ORIENTATION_270:
+ x = float(x - mRawPointerAxes.x.minValue) * mXScale;
+ y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
+ break;
+ default:
+ x = float(x - mRawPointerAxes.x.minValue) * mXScale;
+ y = float(y - mRawPointerAxes.y.minValue) * mYScale;
+ break;
+ }
+}
+
bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
- const float scaledX = x * mXScale;
- const float scaledY = y * mYScale;
+ float xTransformed = x, yTransformed = y;
+ rotateAndScale(xTransformed, yTransformed);
return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
- scaledX >= mSurfaceLeft && scaledX <= mSurfaceLeft + mSurfaceWidth &&
+ xTransformed >= mSurfaceLeft && xTransformed <= mSurfaceLeft + mSurfaceWidth &&
y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
- scaledY >= mSurfaceTop && scaledY <= mSurfaceTop + mSurfaceHeight;
+ yTransformed >= mSurfaceTop && yTransformed <= mSurfaceTop + mSurfaceHeight;
}
const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 89c017d..4b1c0cb 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -758,6 +758,7 @@
static void assignPointerIds(const RawState* last, RawState* current);
const char* modeToString(DeviceMode deviceMode);
+ void rotateAndScale(float& x, float& y);
};
} // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 31b1652..028fb6f 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -6614,20 +6614,41 @@
MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
- // Let surface be different from physical display.
- std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- internalViewport->logicalLeft = internalViewport->physicalTop + 20;
- internalViewport->logicalTop = internalViewport->physicalRight + 20;
- internalViewport->logicalRight = internalViewport->physicalRight - 20;
- internalViewport->logicalBottom = internalViewport->physicalBottom - 20;
- mFakePolicy->updateViewport(internalViewport.value());
-
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
- int32_t rawX = 10;
- int32_t rawY = 10;
+ // Touch on left-top area should work.
+ int32_t rawX = DISPLAY_WIDTH / 2 - 1;
+ int32_t rawY = DISPLAY_HEIGHT / 2 - 1;
+ processPosition(mapper, rawX, rawY);
+ processSync(mapper);
+
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+
+ // Reset.
+ mapper->reset(ARBITRARY_TIME);
+
+ // Let logical display be different to physical display and rotate 90-degrees.
+ std::optional<DisplayViewport> internalViewport =
+ mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ internalViewport->orientation = DISPLAY_ORIENTATION_90;
+ internalViewport->logicalLeft = 0;
+ internalViewport->logicalTop = 0;
+ internalViewport->logicalRight = DISPLAY_HEIGHT;
+ internalViewport->logicalBottom = DISPLAY_WIDTH / 2;
+
+ internalViewport->physicalLeft = DISPLAY_HEIGHT;
+ internalViewport->physicalTop = DISPLAY_WIDTH / 2;
+ internalViewport->physicalRight = DISPLAY_HEIGHT;
+ internalViewport->physicalBottom = DISPLAY_WIDTH;
+
+ internalViewport->deviceWidth = DISPLAY_HEIGHT;
+ internalViewport->deviceHeight = DISPLAY_WIDTH;
+ mFakePolicy->updateViewport(internalViewport.value());
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+ // Display align to right-top after rotate 90-degrees, touch on left-top area should not work.
processPosition(mapper, rawX, rawY);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());