Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e837cc8 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Refactor axis initialization logic

Move the code to a separate function to make it easier to follow.

Bug: 198472780
Test: none
Change-Id: Ic881814ec8cee8bb5535ed80bb6ae92f60d6b1a0
parent f47c339e
Loading
Loading
Loading
Loading
+226 −236
Original line number Diff line number Diff line
@@ -609,215 +609,16 @@ std::optional<DisplayViewport> TouchInputMapper::findViewport() {
    return std::make_optional(newViewport);
}

void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) {
    DeviceMode oldDeviceMode = mDeviceMode;

    resolveExternalStylusPresence();

    // Determine device mode.
    if (mParameters.deviceType == Parameters::DeviceType::POINTER &&
        mConfig.pointerGesturesEnabled && !mConfig.pointerCaptureRequest.enable) {
        mSource = AINPUT_SOURCE_MOUSE;
        mDeviceMode = DeviceMode::POINTER;
        if (hasStylus()) {
            mSource |= AINPUT_SOURCE_STYLUS;
        }
    } else if (isTouchScreen()) {
        mSource = AINPUT_SOURCE_TOUCHSCREEN;
        mDeviceMode = DeviceMode::DIRECT;
        if (hasStylus()) {
            mSource |= AINPUT_SOURCE_STYLUS;
        }
        if (hasExternalStylus()) {
            mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
        }
    } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION) {
        mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
        mDeviceMode = DeviceMode::NAVIGATION;
    } else {
        mSource = AINPUT_SOURCE_TOUCHPAD;
        mDeviceMode = DeviceMode::UNSCALED;
    }

    // Ensure we have valid X and Y axes.
    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
        ALOGW("Touch device '%s' did not report support for X or Y axis!  "
              "The device will be inoperable.",
              getDeviceName().c_str());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    // Get associated display dimensions.
    std::optional<DisplayViewport> newViewport = findViewport();
    if (!newViewport) {
        ALOGI("Touch device '%s' could not query the properties of its associated "
              "display.  The device will be inoperable until the display size "
              "becomes available.",
              getDeviceName().c_str());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    if (!newViewport->isActive) {
        ALOGI("Disabling %s (device %i) because the associated viewport is not active",
              getDeviceName().c_str(), getDeviceId());
        mDeviceMode = DeviceMode::DISABLED;
void TouchInputMapper::initializeSizeRanges() {
    if (mCalibration.sizeCalibration == Calibration::SizeCalibration::NONE) {
        mSizeScale = 0.0f;
        return;
    }

    // Raw width and height in the natural orientation.
    const int32_t rawWidth = mRawPointerAxes.getRawWidth();
    const int32_t rawHeight = mRawPointerAxes.getRawHeight();

    const bool viewportChanged = mViewport != *newViewport;
    bool skipViewportUpdate = false;
    if (viewportChanged) {
        const bool viewportOrientationChanged = mViewport.orientation != newViewport->orientation;
        mViewport = *newViewport;

        if (mDeviceMode == DeviceMode::DIRECT || mDeviceMode == DeviceMode::POINTER) {
            // Convert rotated viewport to the natural orientation.
            int32_t naturalPhysicalWidth, naturalPhysicalHeight;
            int32_t naturalPhysicalLeft, naturalPhysicalTop;
            int32_t naturalDeviceWidth, naturalDeviceHeight;

            // Apply the inverse of the input device orientation so that the input device is
            // configured in the same orientation as the viewport. The input device orientation will
            // be re-applied by mInputDeviceOrientation.
            const int32_t naturalDeviceOrientation =
                    (mViewport.orientation - static_cast<int32_t>(mParameters.orientation) + 4) % 4;
            switch (naturalDeviceOrientation) {
                case DISPLAY_ORIENTATION_90:
                    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:
                    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:
                    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:
                    naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
                    naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
                    naturalPhysicalLeft = mViewport.physicalLeft;
                    naturalPhysicalTop = mViewport.physicalTop;
                    naturalDeviceWidth = mViewport.deviceWidth;
                    naturalDeviceHeight = mViewport.deviceHeight;
                    break;
            }

            if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
                ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
                naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
                naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
            }

            mPhysicalWidth = naturalPhysicalWidth;
            mPhysicalHeight = naturalPhysicalHeight;
            mPhysicalLeft = naturalPhysicalLeft;
            mPhysicalTop = naturalPhysicalTop;

            const int32_t oldDisplayWidth = mDisplayWidth;
            const int32_t oldDisplayHeight = mDisplayHeight;
            mDisplayWidth = naturalDeviceWidth;
            mDisplayHeight = naturalDeviceHeight;

            // InputReader works in the un-rotated display coordinate space, so we don't need to do
            // anything if the device is already orientation-aware. If the device is not
            // orientation-aware, then we need to apply the inverse rotation of the display so that
            // when the display rotation is applied later as a part of the per-window transform, we
            // get the expected screen coordinates.
            mInputDeviceOrientation = mParameters.orientationAware
                    ? DISPLAY_ORIENTATION_0
                    : getInverseRotation(mViewport.orientation);
            // For orientation-aware devices that work in the un-rotated coordinate space, the
            // viewport update should be skipped if it is only a change in the orientation.
            skipViewportUpdate = mParameters.orientationAware && mDisplayWidth == oldDisplayWidth &&
                    mDisplayHeight == oldDisplayHeight && viewportOrientationChanged;

            // Apply the input device orientation for the device.
            mInputDeviceOrientation =
                    (mInputDeviceOrientation + static_cast<int32_t>(mParameters.orientation)) % 4;
        } else {
            mPhysicalWidth = rawWidth;
            mPhysicalHeight = rawHeight;
            mPhysicalLeft = 0;
            mPhysicalTop = 0;

            mDisplayWidth = rawWidth;
            mDisplayHeight = rawHeight;
            mInputDeviceOrientation = DISPLAY_ORIENTATION_0;
        }
    }

    // If moving between pointer modes, need to reset some state.
    bool deviceModeChanged = mDeviceMode != oldDeviceMode;
    if (deviceModeChanged) {
        mOrientedRanges.clear();
    }

    // Create pointer controller if needed, and keep it around if Pointer Capture is enabled to
    // preserve the cursor position.
    if (mDeviceMode == DeviceMode::POINTER ||
        (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches) ||
        (mParameters.deviceType == Parameters::DeviceType::POINTER &&
         mConfig.pointerCaptureRequest.enable)) {
        if (mPointerController == nullptr) {
            mPointerController = getContext()->getPointerController(getDeviceId());
        }
        if (mConfig.pointerCaptureRequest.enable) {
            mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
        }
    } else {
        mPointerController.reset();
    }

    if ((viewportChanged && !skipViewportUpdate) || deviceModeChanged) {
        ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
              "display id %d",
              getDeviceId(), getDeviceName().c_str(), mDisplayWidth, mDisplayHeight,
              mInputDeviceOrientation, mDeviceMode, mViewport.displayId);

        // Configure X and Y factors.
        mXScale = float(mDisplayWidth) / rawWidth;
        mYScale = float(mDisplayHeight) / rawHeight;
        mXPrecision = 1.0f / mXScale;
        mYPrecision = 1.0f / mYScale;

        mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
        mOrientedRanges.x.source = mSource;
        mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
        mOrientedRanges.y.source = mSource;

        configureVirtualKeys();

        // Scale factor for terms that are not oriented in a particular axis.
        // If the pixels are square then xScale == yScale otherwise we fake it
        // by choosing an average.
        mGeometricScale = avg(mXScale, mYScale);

    // Size of diagonal axis.
        float diagonalSize = hypotf(mDisplayWidth, mDisplayHeight);
    const float diagonalSize = hypotf(mDisplayWidth, mDisplayHeight);

    // Size factors.
        if (mCalibration.sizeCalibration != Calibration::SizeCalibration::NONE) {
    if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) {
        mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
    } else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) {
@@ -859,10 +660,27 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded)
    mOrientedRanges.size.flat = 0;
    mOrientedRanges.size.fuzz = 0;
    mOrientedRanges.size.resolution = 0;
        } else {
            mSizeScale = 0.0f;
}

void TouchInputMapper::initializeOrientedRanges() {
    // Configure X and Y factors.
    mXScale = float(mDisplayWidth) / mRawPointerAxes.getRawWidth();
    mYScale = float(mDisplayHeight) / mRawPointerAxes.getRawHeight();
    mXPrecision = 1.0f / mXScale;
    mYPrecision = 1.0f / mYScale;

    mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
    mOrientedRanges.x.source = mSource;
    mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
    mOrientedRanges.y.source = mSource;

    // Scale factor for terms that are not oriented in a particular axis.
    // If the pixels are square then xScale == yScale otherwise we fake it
    // by choosing an average.
    mGeometricScale = avg(mXScale, mYScale);

    initializeSizeRanges();

    // Pressure factors.
    mPressureScale = 0;
    float pressureMax = 1.0;
@@ -926,8 +744,7 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded)
        mOrientedRanges.orientation.flat = 0;
        mOrientedRanges.orientation.fuzz = 0;
        mOrientedRanges.orientation.resolution = 0;
        } else if (mCalibration.orientationCalibration !=
                   Calibration::OrientationCalibration::NONE) {
    } else if (mCalibration.orientationCalibration != Calibration::OrientationCalibration::NONE) {
        if (mCalibration.orientationCalibration ==
            Calibration::OrientationCalibration::INTERPOLATED) {
            if (mRawPointerAxes.orientation.valid) {
@@ -1013,6 +830,197 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded)
            mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
            break;
    }
}

void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) {
    DeviceMode oldDeviceMode = mDeviceMode;

    resolveExternalStylusPresence();

    // Determine device mode.
    if (mParameters.deviceType == Parameters::DeviceType::POINTER &&
        mConfig.pointerGesturesEnabled && !mConfig.pointerCaptureRequest.enable) {
        mSource = AINPUT_SOURCE_MOUSE;
        mDeviceMode = DeviceMode::POINTER;
        if (hasStylus()) {
            mSource |= AINPUT_SOURCE_STYLUS;
        }
    } else if (isTouchScreen()) {
        mSource = AINPUT_SOURCE_TOUCHSCREEN;
        mDeviceMode = DeviceMode::DIRECT;
        if (hasStylus()) {
            mSource |= AINPUT_SOURCE_STYLUS;
        }
        if (hasExternalStylus()) {
            mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
        }
    } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION) {
        mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
        mDeviceMode = DeviceMode::NAVIGATION;
    } else {
        mSource = AINPUT_SOURCE_TOUCHPAD;
        mDeviceMode = DeviceMode::UNSCALED;
    }

    // Ensure we have valid X and Y axes.
    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
        ALOGW("Touch device '%s' did not report support for X or Y axis!  "
              "The device will be inoperable.",
              getDeviceName().c_str());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    // Get associated display dimensions.
    std::optional<DisplayViewport> newViewport = findViewport();
    if (!newViewport) {
        ALOGI("Touch device '%s' could not query the properties of its associated "
              "display.  The device will be inoperable until the display size "
              "becomes available.",
              getDeviceName().c_str());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    if (!newViewport->isActive) {
        ALOGI("Disabling %s (device %i) because the associated viewport is not active",
              getDeviceName().c_str(), getDeviceId());
        mDeviceMode = DeviceMode::DISABLED;
        return;
    }

    // Raw width and height in the natural orientation.
    const int32_t rawWidth = mRawPointerAxes.getRawWidth();
    const int32_t rawHeight = mRawPointerAxes.getRawHeight();

    const bool viewportChanged = mViewport != *newViewport;
    bool skipViewportUpdate = false;
    if (viewportChanged) {
        const bool viewportOrientationChanged = mViewport.orientation != newViewport->orientation;
        mViewport = *newViewport;

        if (mDeviceMode == DeviceMode::DIRECT || mDeviceMode == DeviceMode::POINTER) {
            // Convert rotated viewport to the natural orientation.
            int32_t naturalPhysicalWidth, naturalPhysicalHeight;
            int32_t naturalPhysicalLeft, naturalPhysicalTop;
            int32_t naturalDeviceWidth, naturalDeviceHeight;

            // Apply the inverse of the input device orientation so that the input device is
            // configured in the same orientation as the viewport. The input device orientation will
            // be re-applied by mInputDeviceOrientation.
            const int32_t naturalDeviceOrientation =
                    (mViewport.orientation - static_cast<int32_t>(mParameters.orientation) + 4) % 4;
            switch (naturalDeviceOrientation) {
                case DISPLAY_ORIENTATION_90:
                    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:
                    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:
                    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:
                    naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
                    naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
                    naturalPhysicalLeft = mViewport.physicalLeft;
                    naturalPhysicalTop = mViewport.physicalTop;
                    naturalDeviceWidth = mViewport.deviceWidth;
                    naturalDeviceHeight = mViewport.deviceHeight;
                    break;
            }

            if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
                ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
                naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
                naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
            }

            mPhysicalWidth = naturalPhysicalWidth;
            mPhysicalHeight = naturalPhysicalHeight;
            mPhysicalLeft = naturalPhysicalLeft;
            mPhysicalTop = naturalPhysicalTop;

            const int32_t oldDisplayWidth = mDisplayWidth;
            const int32_t oldDisplayHeight = mDisplayHeight;
            mDisplayWidth = naturalDeviceWidth;
            mDisplayHeight = naturalDeviceHeight;

            // InputReader works in the un-rotated display coordinate space, so we don't need to do
            // anything if the device is already orientation-aware. If the device is not
            // orientation-aware, then we need to apply the inverse rotation of the display so that
            // when the display rotation is applied later as a part of the per-window transform, we
            // get the expected screen coordinates.
            mInputDeviceOrientation = mParameters.orientationAware
                    ? DISPLAY_ORIENTATION_0
                    : getInverseRotation(mViewport.orientation);
            // For orientation-aware devices that work in the un-rotated coordinate space, the
            // viewport update should be skipped if it is only a change in the orientation.
            skipViewportUpdate = mParameters.orientationAware && mDisplayWidth == oldDisplayWidth &&
                    mDisplayHeight == oldDisplayHeight && viewportOrientationChanged;

            // Apply the input device orientation for the device.
            mInputDeviceOrientation =
                    (mInputDeviceOrientation + static_cast<int32_t>(mParameters.orientation)) % 4;
        } else {
            mPhysicalWidth = rawWidth;
            mPhysicalHeight = rawHeight;
            mPhysicalLeft = 0;
            mPhysicalTop = 0;

            mDisplayWidth = rawWidth;
            mDisplayHeight = rawHeight;
            mInputDeviceOrientation = DISPLAY_ORIENTATION_0;
        }
    }

    // If moving between pointer modes, need to reset some state.
    bool deviceModeChanged = mDeviceMode != oldDeviceMode;
    if (deviceModeChanged) {
        mOrientedRanges.clear();
    }

    // Create pointer controller if needed, and keep it around if Pointer Capture is enabled to
    // preserve the cursor position.
    if (mDeviceMode == DeviceMode::POINTER ||
        (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches) ||
        (mParameters.deviceType == Parameters::DeviceType::POINTER &&
         mConfig.pointerCaptureRequest.enable)) {
        if (mPointerController == nullptr) {
            mPointerController = getContext()->getPointerController(getDeviceId());
        }
        if (mConfig.pointerCaptureRequest.enable) {
            mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
        }
    } else {
        mPointerController.reset();
    }

    if ((viewportChanged && !skipViewportUpdate) || deviceModeChanged) {
        ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
              "display id %d",
              getDeviceId(), getDeviceName().c_str(), mDisplayWidth, mDisplayHeight,
              mInputDeviceOrientation, mDeviceMode, mViewport.displayId);

        configureVirtualKeys();

        initializeOrientedRanges();

        // Location
        updateAffineTransformation();
@@ -1267,26 +1275,8 @@ void TouchInputMapper::resolveCalibration() {
void TouchInputMapper::dumpCalibration(std::string& dump) {
    dump += INDENT3 "Calibration:\n";

    // Size
    switch (mCalibration.sizeCalibration) {
        case Calibration::SizeCalibration::NONE:
            dump += INDENT4 "touch.size.calibration: none\n";
            break;
        case Calibration::SizeCalibration::GEOMETRIC:
            dump += INDENT4 "touch.size.calibration: geometric\n";
            break;
        case Calibration::SizeCalibration::DIAMETER:
            dump += INDENT4 "touch.size.calibration: diameter\n";
            break;
        case Calibration::SizeCalibration::BOX:
            dump += INDENT4 "touch.size.calibration: box\n";
            break;
        case Calibration::SizeCalibration::AREA:
            dump += INDENT4 "touch.size.calibration: area\n";
            break;
        default:
            ALOG_ASSERT(false);
    }
    dump += INDENT4 "touch.size.calibration: ";
    dump += ftl::enum_string(mCalibration.sizeCalibration) + "\n";

    if (mCalibration.haveSizeScale) {
        dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n", mCalibration.sizeScale);
+4 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@ protected:
            DIAMETER,
            BOX,
            AREA,
            ftl_last = AREA
        };

        SizeCalibration sizeCalibration;
@@ -732,6 +733,9 @@ private:
    void resetExternalStylus();
    void clearStylusDataPendingFlags();

    void initializeOrientedRanges();
    void initializeSizeRanges();

    void sync(nsecs_t when, nsecs_t readTime);

    bool consumeRawTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags);