diff options
| -rw-r--r-- | include/android/surface_control.h | 8 | ||||
| -rw-r--r-- | libs/binder/include/binder/AppOpsManager.h | 11 | ||||
| -rw-r--r-- | libs/nativewindow/include/android/native_window.h | 12 | ||||
| -rw-r--r-- | services/inputflinger/reader/mapper/TouchInputMapper.cpp | 106 | ||||
| -rw-r--r-- | services/inputflinger/reader/mapper/TouchInputMapper.h | 8 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 170 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 35 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/main_surfaceflinger.cpp | 7 |
9 files changed, 240 insertions, 120 deletions
diff --git a/include/android/surface_control.h b/include/android/surface_control.h index c30dcfee09..cbcf6ec5c0 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -409,7 +409,7 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio #if __ANDROID_API__ >= 30 -/* +/** * Sets the intended frame rate for |surface_control|. * * On devices that are capable of running the display at different refresh rates, the system may @@ -421,9 +421,9 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio * * |frameRate| is the intended frame rate of this surface, in frames per second. 0 is a special * value that indicates the app will accept the system's choice for the display frame rate, which is - * the default behavior if this function isn't called. The frameRate param does *not* need to be a - * valid refresh rate for this device's display - e.g., it's fine to pass 30fps to a device that can - * only run the display at 60fps. + * the default behavior if this function isn't called. The frameRate param does <em>not</em> need to + * be a valid refresh rate for this device's display - e.g., it's fine to pass 30fps to a device + * that can only run the display at 60fps. * * |compatibility| The frame rate compatibility of this surface. The compatibility value may * influence the system's choice of display frame rate. To specify a compatibility use the diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h index 2ee5930f2b..6afcd77e70 100644 --- a/libs/binder/include/binder/AppOpsManager.h +++ b/libs/binder/include/binder/AppOpsManager.h @@ -122,7 +122,16 @@ public: OP_LEGACY_STORAGE = 87, OP_ACCESS_ACCESSIBILITY = 88, OP_READ_DEVICE_IDENTIFIERS = 89, - _NUM_OP = 90 + OP_ACCESS_MEDIA_LOCATION = 90, + OP_QUERY_ALL_PACKAGES = 91, + OP_MANAGE_EXTERNAL_STORAGE = 92, + OP_INTERACT_ACROSS_PROFILES = 93, + OP_ACTIVATE_PLATFORM_VPN = 94, + OP_LOADER_USAGE_STATS = 95, + OP_DEPRECATED_1 = 96, + OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97, + OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98, + _NUM_OP = 99 }; AppOpsManager(); diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h index 59aa6655b8..25130e2a03 100644 --- a/libs/nativewindow/include/android/native_window.h +++ b/libs/nativewindow/include/android/native_window.h @@ -233,15 +233,15 @@ int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN #if __ANDROID_API__ >= 30 -/* Parameter for ANativeWindow_setFrameRate */ -enum { +/** Compatibility value for ANativeWindow_setFrameRate. */ +enum ANativeWindow_FrameRateCompatibility { /** * There are no inherent restrictions on the frame rate of this window. */ ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT = 0, /** * This window is being used to display content with an inherently fixed - * frame rate, e.g. a video that has a specific frame rate. When the system + * frame rate, e.g.\ a video that has a specific frame rate. When the system * selects a frame rate other than what the app requested, the app will need * to do pull down or use some other technique to adapt to the system's * frame rate. The user experience is likely to be worse (e.g. more frame @@ -272,9 +272,9 @@ enum { * \param frameRate The intended frame rate of this window, in frames per * second. 0 is a special value that indicates the app will accept the system's * choice for the display frame rate, which is the default behavior if this - * function isn't called. The frameRate param does *not* need to be a valid - * refresh rate for this device's display - e.g., it's fine to pass 30fps to a - * device that can only run the display at 60fps. + * function isn't called. The frameRate param does <em>not</em> need to be a + * valid refresh rate for this device's display - e.g., it's fine to pass 30fps + * to a device that can only run the display at 60fps. * * \param compatibility The frame rate compatibility of this window. The * compatibility value may influence the system's choice of display refresh diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index bbc8e537c6..99a572a5fd 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -160,8 +160,8 @@ TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext) : InputMapper(deviceContext), mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), - mSurfaceWidth(-1), - mSurfaceHeight(-1), + mRawSurfaceWidth(-1), + mRawSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), mPhysicalWidth(-1), @@ -680,7 +680,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 - naturalPhysicalWidth; + naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom; naturalPhysicalTop = mViewport.physicalLeft; naturalDeviceWidth = mViewport.deviceHeight; naturalDeviceHeight = mViewport.deviceWidth; @@ -701,7 +701,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 - naturalPhysicalHeight; + naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight; naturalDeviceWidth = mViewport.deviceHeight; naturalDeviceHeight = mViewport.deviceWidth; break; @@ -729,10 +729,12 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPhysicalLeft = naturalPhysicalLeft; mPhysicalTop = naturalPhysicalTop; - mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; - mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; + mRawSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; + mRawSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; + mSurfaceRight = mSurfaceLeft + naturalLogicalWidth; + mSurfaceBottom = mSurfaceTop + naturalLogicalHeight; mSurfaceOrientation = mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0; @@ -742,8 +744,8 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPhysicalLeft = 0; mPhysicalTop = 0; - mSurfaceWidth = rawWidth; - mSurfaceHeight = rawHeight; + mRawSurfaceWidth = rawWidth; + mRawSurfaceHeight = rawHeight; mSurfaceLeft = 0; mSurfaceTop = 0; mSurfaceOrientation = DISPLAY_ORIENTATION_0; @@ -769,12 +771,12 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { if (viewportChanged || deviceModeChanged) { ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, " "display id %d", - getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight, + getDeviceId(), getDeviceName().c_str(), mRawSurfaceWidth, mRawSurfaceHeight, mSurfaceOrientation, mDeviceMode, mViewport.displayId); // Configure X and Y factors. - mXScale = float(mSurfaceWidth) / rawWidth; - mYScale = float(mSurfaceHeight) / rawHeight; + mXScale = float(mRawSurfaceWidth) / rawWidth; + mYScale = float(mRawSurfaceHeight) / rawHeight; mXTranslate = -mSurfaceLeft; mYTranslate = -mSurfaceTop; mXPrecision = 1.0f / mXScale; @@ -793,7 +795,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mGeometricScale = avg(mXScale, mYScale); // Size of diagonal axis. - float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight); + float diagonalSize = hypotf(mRawSurfaceWidth, mRawSurfaceHeight); // Size factors. if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { @@ -956,13 +958,13 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mOrientedYPrecision = mXPrecision; mOrientedRanges.x.min = mYTranslate; - mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1; + mOrientedRanges.x.max = mRawSurfaceHeight + mYTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = 0; mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale; mOrientedRanges.y.min = mXTranslate; - mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1; + mOrientedRanges.y.max = mRawSurfaceWidth + mXTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = 0; mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale; @@ -973,13 +975,13 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mOrientedYPrecision = mYPrecision; mOrientedRanges.x.min = mXTranslate; - mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1; + mOrientedRanges.x.max = mRawSurfaceWidth + mXTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = 0; mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale; mOrientedRanges.y.min = mYTranslate; - mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1; + mOrientedRanges.y.max = mRawSurfaceHeight + mYTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = 0; mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale; @@ -992,7 +994,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { if (mDeviceMode == DEVICE_MODE_POINTER) { // Compute pointer gesture detection parameters. float rawDiagonal = hypotf(rawWidth, rawHeight); - float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight); + float displayDiagonal = hypotf(mRawSurfaceWidth, mRawSurfaceHeight); // 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 @@ -1027,10 +1029,12 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { void TouchInputMapper::dumpSurface(std::string& dump) { dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str()); - dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth); - dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); + dump += StringPrintf(INDENT3 "RawSurfaceWidth: %dpx\n", mRawSurfaceWidth); + dump += StringPrintf(INDENT3 "RawSurfaceHeight: %dpx\n", mRawSurfaceHeight); dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); + dump += StringPrintf(INDENT3 "SurfaceRight: %d\n", mSurfaceRight); + dump += StringPrintf(INDENT3 "SurfaceBottom: %d\n", mSurfaceBottom); dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth); dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight); dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft); @@ -1074,16 +1078,16 @@ void TouchInputMapper::configureVirtualKeys() { int32_t halfHeight = virtualKeyDefinition.height / 2; virtualKey.hitLeft = - (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mSurfaceWidth + + (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mRawSurfaceWidth + touchScreenLeft; virtualKey.hitRight = - (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mSurfaceWidth + + (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mRawSurfaceWidth + touchScreenLeft; - virtualKey.hitTop = - (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight / mSurfaceHeight + + virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight / + mRawSurfaceHeight + touchScreenTop; - virtualKey.hitBottom = - (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / mSurfaceHeight + + virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / + mRawSurfaceHeight + touchScreenTop; mVirtualKeys.push_back(virtualKey); } @@ -2188,13 +2192,10 @@ void TouchInputMapper::cookPointerData() { rotateAndScale(xTransformed, yTransformed); // Adjust X, Y, and coverage coords for surface orientation. - float x, y; float left, top, right, bottom; switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: - 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; @@ -2207,8 +2208,6 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_180: - 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; @@ -2221,8 +2220,6 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_270: - 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; @@ -2235,8 +2232,6 @@ void TouchInputMapper::cookPointerData() { } break; default: - 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; @@ -2247,8 +2242,8 @@ void TouchInputMapper::cookPointerData() { // Write output coords. PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i]; out.clear(); - out.setAxisValue(AMOTION_EVENT_AXIS_X, x); - out.setAxisValue(AMOTION_EVENT_AXIS_Y, y); + out.setAxisValue(AMOTION_EVENT_AXIS_X, xTransformed); + out.setAxisValue(AMOTION_EVENT_AXIS_Y, yTransformed); out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure); out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size); out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor); @@ -3624,34 +3619,47 @@ void TouchInputMapper::cancelTouch(nsecs_t when) { abortTouches(when, 0 /* policyFlags*/); } +// Transform raw coordinate to surface coordinate void TouchInputMapper::rotateAndScale(float& x, float& y) { + // Scale to surface coordinate. + const float xScaled = float(x - mRawPointerAxes.x.minValue) * mXScale; + const float yScaled = float(y - mRawPointerAxes.y.minValue) * mYScale; + + // Rotate to surface coordinate. + // 0 - no swap and reverse. + // 90 - swap x/y and reverse y. + // 180 - reverse x, y. + // 270 - swap x/y and reverse x. switch (mSurfaceOrientation) { + case DISPLAY_ORIENTATION_0: + x = xScaled + mXTranslate; + y = yScaled + mYTranslate; + break; case DISPLAY_ORIENTATION_90: - x = float(mRawPointerAxes.x.maxValue - x) * mXScale; - y = float(y - mRawPointerAxes.y.minValue) * mYScale; + y = mSurfaceRight - xScaled; + x = yScaled + mYTranslate; break; case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - x) * mXScale; - y = float(mRawPointerAxes.y.maxValue - y) * mYScale; + x = mSurfaceRight - xScaled; + y = mSurfaceBottom - yScaled; break; case DISPLAY_ORIENTATION_270: - x = float(x - mRawPointerAxes.x.minValue) * mXScale; - y = float(mRawPointerAxes.y.maxValue - y) * mYScale; + y = xScaled + mXTranslate; + x = mSurfaceBottom - yScaled; break; default: - x = float(x - mRawPointerAxes.x.minValue) * mXScale; - y = float(y - mRawPointerAxes.y.minValue) * mYScale; - break; + assert(false); } } bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { - float xTransformed = x, yTransformed = y; - rotateAndScale(xTransformed, yTransformed); + const float xScaled = (x - mRawPointerAxes.x.minValue) * mXScale; + const float yScaled = (y - mRawPointerAxes.y.minValue) * mYScale; + return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue && - xTransformed >= mSurfaceLeft && xTransformed <= mSurfaceLeft + mSurfaceWidth && + xScaled >= mSurfaceLeft && xScaled <= mSurfaceRight && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue && - yTransformed >= mSurfaceTop && yTransformed <= mSurfaceTop + mSurfaceHeight; + yScaled >= mSurfaceTop && yScaled <= mSurfaceBottom; } 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 e21a33abed..58bfc5c596 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -407,12 +407,16 @@ private: // 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. + // They could be used for calculating diagonal, scaling factors, and virtual keys. + int32_t mRawSurfaceWidth; + int32_t mRawSurfaceHeight; + // The surface origin specifies how the surface coordinates should be translated // to align with the logical display coordinate space. - int32_t mSurfaceWidth; - int32_t mSurfaceHeight; int32_t mSurfaceLeft; int32_t mSurfaceTop; + int32_t mSurfaceRight; + int32_t mSurfaceBottom; // Similar to the surface coordinates, but in the raw display coordinate space rather than in // the logical coordinate space. diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 618aefc741..96d86b68fc 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -6990,51 +6990,7 @@ TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) { ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId); } -/** - * Test touch should not work if outside of surface. - */ -TEST_F(MultiTouchInputMapperTest, Viewports_SurfaceRange) { - addConfigurationProperty("touch.deviceType", "touchScreen"); - prepareDisplay(DISPLAY_ORIENTATION_0); - prepareAxes(POSITION); - MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); - - // 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()); -} TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) { addConfigurationProperty("touch.deviceType", "touchScreen"); @@ -7161,4 +7117,130 @@ TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) { ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId); } + +/** + * Test touch should not work if outside of surface. + */ +class MultiTouchInputMapperTest_SurfaceRange : public MultiTouchInputMapperTest { +protected: + void halfDisplayToCenterHorizontal(int32_t orientation) { + std::optional<DisplayViewport> internalViewport = + mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL); + + // Half display to (width/4, 0, width * 3/4, height) to make display has offset. + internalViewport->orientation = orientation; + if (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270) { + internalViewport->logicalLeft = 0; + internalViewport->logicalTop = 0; + internalViewport->logicalRight = DISPLAY_HEIGHT; + internalViewport->logicalBottom = DISPLAY_WIDTH / 2; + + internalViewport->physicalLeft = 0; + internalViewport->physicalTop = DISPLAY_WIDTH / 4; + internalViewport->physicalRight = DISPLAY_HEIGHT; + internalViewport->physicalBottom = DISPLAY_WIDTH * 3 / 4; + + internalViewport->deviceWidth = DISPLAY_HEIGHT; + internalViewport->deviceHeight = DISPLAY_WIDTH; + } else { + internalViewport->logicalLeft = 0; + internalViewport->logicalTop = 0; + internalViewport->logicalRight = DISPLAY_WIDTH / 2; + internalViewport->logicalBottom = DISPLAY_HEIGHT; + + internalViewport->physicalLeft = DISPLAY_WIDTH / 4; + internalViewport->physicalTop = 0; + internalViewport->physicalRight = DISPLAY_WIDTH * 3 / 4; + internalViewport->physicalBottom = DISPLAY_HEIGHT; + + internalViewport->deviceWidth = DISPLAY_WIDTH; + internalViewport->deviceHeight = DISPLAY_HEIGHT; + } + + mFakePolicy->updateViewport(internalViewport.value()); + configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + } + + void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xInside, int32_t yInside, + int32_t xOutside, int32_t yOutside, int32_t xExpected, + int32_t yExpected) { + // touch on outside area should not work. + processPosition(mapper, toRawX(xOutside), toRawY(yOutside)); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); + + // touch on inside area should receive the event. + NotifyMotionArgs args; + processPosition(mapper, toRawX(xInside), toRawY(yInside)); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_NEAR(xExpected, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); + ASSERT_NEAR(yExpected, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); + + // Reset. + mapper.reset(ARBITRARY_TIME); + } +}; + +TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION); + MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); + + // Touch on center of normal display should work. + const int32_t x = DISPLAY_WIDTH / 4; + const int32_t y = DISPLAY_HEIGHT / 2; + processPosition(mapper, toRawX(x), toRawY(y)); + processSync(mapper); + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], x, y, 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f)); + // Reset. + mapper.reset(ARBITRARY_TIME); + + // Let physical display be different to device, and make surface and physical could be 1:1. + halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_0); + + const int32_t xExpected = (x + 1) - (DISPLAY_WIDTH / 4); + const int32_t yExpected = y; + processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); +} + +TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION); + MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); + + // Half display to (width/4, 0, width * 3/4, height) and rotate 90-degrees. + halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_90); + + const int32_t x = DISPLAY_WIDTH / 4; + const int32_t y = DISPLAY_HEIGHT / 2; + + // expect x/y = swap x/y then reverse y. + const int32_t xExpected = y; + const int32_t yExpected = (DISPLAY_WIDTH * 3 / 4) - (x + 1); + processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); +} + +TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION); + MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); + + // Half display to (width/4, 0, width * 3/4, height) and rotate 270-degrees. + halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_270); + + const int32_t x = DISPLAY_WIDTH / 4; + const int32_t y = DISPLAY_HEIGHT / 2; + + // expect x/y = swap x/y then reverse x. + constexpr int32_t xExpected = DISPLAY_HEIGHT - y; + constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4; + processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); +} } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 34d6d3133c..880be28eac 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4142,6 +4142,9 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int } if (currentMode == HWC_POWER_MODE_OFF) { + if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) { + ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno)); + } getHwComposer().setPowerMode(*displayId, mode); if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) { setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState); @@ -4152,19 +4155,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mVisibleRegionsDirty = true; mHasPoweredOff = true; repaintEverything(); - - struct sched_param param = {0}; - param.sched_priority = 1; - if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { - ALOGW("Couldn't set SCHED_FIFO on display on"); - } } else if (mode == HWC_POWER_MODE_OFF) { // Turn off the display - struct sched_param param = {0}; - if (sched_setscheduler(0, SCHED_OTHER, ¶m) != 0) { - ALOGW("Couldn't set SCHED_OTHER on display off"); + if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) { + ALOGW("Couldn't set SCHED_OTHER on display off: %s\n", strerror(errno)); } - if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) { mScheduler->disableHardwareVsync(true); mScheduler->onScreenReleased(mAppConnectionHandle); @@ -5351,6 +5346,26 @@ static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) { } } +status_t SurfaceFlinger::setSchedFifo(bool enabled) { + static constexpr int kFifoPriority = 2; + static constexpr int kOtherPriority = 0; + + struct sched_param param = {0}; + int sched_policy; + if (enabled) { + sched_policy = SCHED_FIFO; + param.sched_priority = kFifoPriority; + } else { + sched_policy = SCHED_OTHER; + param.sched_priority = kOtherPriority; + } + + if (sched_setscheduler(0, sched_policy, ¶m) != 0) { + return -errno; + } + return NO_ERROR; +} + const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack}); if (displayToken) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6ab1fcf9d5..60904f640d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -259,6 +259,9 @@ public: // overhead that is caused by reading from sysprop. static bool useFrameRateApi; + // set main thread scheduling policy + static status_t setSchedFifo(bool enabled) ANDROID_API; + static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index d7ad9deb03..2b8424c987 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -31,6 +31,7 @@ #include <binder/ProcessState.h> #include <configstore/Utils.h> #include <displayservice/DisplayService.h> +#include <errno.h> #include <hidl/LegacySupport.h> #include <processgroup/sched_policy.h> #include "SurfaceFlinger.h" @@ -114,10 +115,8 @@ int main(int, char**) { startDisplayService(); // dependency on SF getting registered above - struct sched_param param = {0}; - param.sched_priority = 2; - if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { - ALOGE("Couldn't set SCHED_FIFO"); + if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) { + ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno)); } // run surface flinger in this thread |