OSDN Git Service

Fix foldable emulator touch does not work
authorArthur Hung <arthurhung@google.com>
Thu, 26 Sep 2019 10:31:26 +0000 (18:31 +0800)
committerArthur Hung <arthurhung@google.com>
Wed, 16 Oct 2019 11:15:06 +0000 (19:15 +0800)
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

services/inputflinger/reader/mapper/TouchInputMapper.cpp
services/inputflinger/reader/mapper/TouchInputMapper.h
services/inputflinger/tests/InputReader_test.cpp

index 34603b9..c80a2dc 100644 (file)
@@ -668,7 +668,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
                     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 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
                     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 @@ void TouchInputMapper::cookPointerData() {
         // 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 @@ void TouchInputMapper::cookPointerData() {
 
         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 @@ void TouchInputMapper::cookPointerData() {
                 }
                 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 @@ void TouchInputMapper::cookPointerData() {
                 }
                 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 @@ void TouchInputMapper::cookPointerData() {
                 }
                 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 @@ void TouchInputMapper::cancelTouch(nsecs_t when) {
     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) {
index 89c017d..4b1c0cb 100644 (file)
@@ -758,6 +758,7 @@ private:
     static void assignPointerIds(const RawState* last, RawState* current);
 
     const char* modeToString(DeviceMode deviceMode);
+    void rotateAndScale(float& x, float& y);
 };
 
 } // namespace android
index 31b1652..028fb6f 100644 (file)
@@ -6614,20 +6614,41 @@ TEST_F(MultiTouchInputMapperTest, Viewports_SurfaceRange) {
     MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
-    // Let surface be different from physical display.
+    prepareAxes(POSITION);
+    addMapperAndConfigure(mapper);
+
+    // 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->logicalLeft = internalViewport->physicalTop + 20;
-    internalViewport->logicalTop = internalViewport->physicalRight + 20;
-    internalViewport->logicalRight = internalViewport->physicalRight - 20;
-    internalViewport->logicalBottom = internalViewport->physicalBottom - 20;
+    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);
 
-    prepareAxes(POSITION);
-    addMapperAndConfigure(mapper);
-
-    int32_t rawX = 10;
-    int32_t rawY = 10;
+    // 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());