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

Commit 1b2c42cd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Refactor axis initialization logic"

parents 510cc5e4 4e837cc8
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);