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

Commit 869b89d2 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

TouchInputMapper: Disable PointerUsage concept with a flag

Introduce a flag to disable the concept of PointerUsage.

TouchInputMapper's POINTER mode was split into several "usages",
including GESTURES, STYLUS, and MOUSE. These sub-modes were used to
process touchpad gestures, drawing tablets, and absolute mice,
respectively.

Now that we no longer use TouchInputMapper for touchpad gestures, we can
safely remove the special processing code for POINTER mode. Most of the
special processing in the POINTER mode pipeline was specific to the
GESTURES usage - for processing touchpad gestures. Without the need for
touchpad gesture processing in TouchInputMapper, the rest of what was
covered by this mode (e.g. the STYLUS and MOUSE usages) can share the
same code as DIRECT mode, since it isn't handling many special cases.
The PointerChoreographer refactor also made it so that POINTER mode no
longer needed to explicitly control mouse/stylus icons on the screen.

After this change, drawing tablets and absolute mice will share the
same code as touchscreens and styluses, so the forked code branches
are unified.

One special case for absolute mouse that was being handled by the
PointerUsage branch was that a mouse is aways hovering unless a mouse
button is pressed. We now account for this special case while cooking
the pointer state.

Bug: 281840344
Bug: 387529073
Bug: 257078296
Test: inputflinger_tests, DrawingTabletTest, AbsoluteMouseTest
Flag: com.android.input.flags.disable_touch_input_mapper_pointer_usage
Change-Id: Icfe99a5948d798a8f26798197e065d519eda693b
parent 5ce9acdf
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -187,6 +187,16 @@ flag {
  is_fixed_read_only: true
}

flag {
  name: "disable_touch_input_mapper_pointer_usage"
  namespace: "input"
  description: "Disable the PointerUsage concept in TouchInputMapper since the old touchpad stack is no longer used."
  bug: "281840344"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "keyboard_repeat_keys"
  namespace: "input"
+30 −4
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@

#include <android-base/stringprintf.h>
#include <android/input.h>
#include <com_android_input_flags.h>
#include <ftl/enum.h>
#include <input/PrintTools.h>
#include <input/PropertyMap.h>
@@ -47,6 +48,8 @@

namespace android {

namespace input_flags = com::android::input::flags;

// --- Constants ---

// Artificial latency on synthetic events created from stylus data without corresponding touch
@@ -1575,7 +1578,8 @@ std::list<NotifyArgs> TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t re
                                mLastCookedState.buttonState, mCurrentCookedState.buttonState);

    // Dispatch the touches either directly or by translation through a pointer on screen.
    if (mDeviceMode == DeviceMode::POINTER) {
    if (!input_flags::disable_touch_input_mapper_pointer_usage() &&
        mDeviceMode == DeviceMode::POINTER) {
        for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits); !idBits.isEmpty();) {
            uint32_t id = idBits.clearFirstMarkedBit();
            const RawPointerData::Pointer& pointer =
@@ -1613,7 +1617,9 @@ std::list<NotifyArgs> TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t re
        }

        out += dispatchPointerUsage(when, readTime, policyFlags, pointerUsage);
    } else {
    }
    if (input_flags::disable_touch_input_mapper_pointer_usage() ||
        mDeviceMode != DeviceMode::POINTER) {
        if (!mCurrentMotionAborted) {
            out += dispatchButtonRelease(when, readTime, policyFlags);
            out += dispatchHoverExit(when, readTime, policyFlags);
@@ -2251,6 +2257,23 @@ void TouchInputMapper::cookPointerData() {
    for (uint32_t i = 0; i < currentPointerCount; i++) {
        const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];

        bool isHovering = in.isHovering;

        // A tool MOUSE pointer is only down/touching when a mouse button is pressed.
        if (input_flags::disable_touch_input_mapper_pointer_usage() &&
            in.toolType == ToolType::MOUSE &&
            !mCurrentRawState.rawPointerData.canceledIdBits.hasBit(in.id)) {
            if (isPointerDown(mCurrentRawState.buttonState)) {
                isHovering = false;
                mCurrentCookedState.cookedPointerData.touchingIdBits.markBit(in.id);
                mCurrentCookedState.cookedPointerData.hoveringIdBits.clearBit(in.id);
            } else {
                isHovering = true;
                mCurrentCookedState.cookedPointerData.touchingIdBits.clearBit(in.id);
                mCurrentCookedState.cookedPointerData.hoveringIdBits.markBit(in.id);
            }
        }

        // Size
        float touchMajor, touchMinor, toolMajor, toolMinor, size;
        switch (mCalibration.sizeCalibration) {
@@ -2340,7 +2363,7 @@ void TouchInputMapper::cookPointerData() {
                pressure = in.pressure * mPressureScale;
                break;
            default:
                pressure = in.isHovering ? 0 : 1;
                pressure = isHovering ? 0 : 1;
                break;
        }

@@ -3697,7 +3720,10 @@ NotifyMotionArgs TouchInputMapper::dispatchMotion(
    float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
    float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
    if (mDeviceMode == DeviceMode::POINTER) {
        xCursorPosition = yCursorPosition = 0.f;
        ALOGW_IF(pointerCount != 1,
                 "Only single pointer events are fully supported in POINTER mode");
        xCursorPosition = pointerCoords[0].getX();
        yCursorPosition = pointerCoords[0].getY();
    }
    const DeviceId deviceId = getDeviceId();
    std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
+4 −1
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ protected:
        DISABLED,   // input is disabled
        DIRECT,     // direct mapping (touchscreen)
        NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
        POINTER,    // pointer mapping (e.g. uncaptured touchpad, drawing tablet)
        POINTER,    // pointer mapping (e.g. absolute mouse, drawing tablet)

        ftl_last = POINTER
    };
@@ -234,6 +234,9 @@ protected:
            ftl_last = POINTER
        };

        // TouchInputMapper will configure devices with INPUT_PROP_DIRECT as
        // DeviceType::TOUCH_SCREEN, and will otherwise use DeviceType::POINTER by default.
        // This can be overridden by IDC files, using the `touch.deviceType` config.
        DeviceType deviceType;
        bool hasAssociatedDisplay;
        bool associatedDisplayIsExternal;
+1 −34
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "FakeInputDispatcherPolicy.h"
#include "FakeInputTracingBackend.h"
#include "FakeWindows.h"
#include "ScopedFlagOverride.h"
#include "TestEventMatchers.h"
#include <NotifyArgsBuilders.h>
@@ -138,40 +139,6 @@ static KeyEvent getTestKeyEvent() {
    return event;
}
/**
 * Provide a local override for a flag value. The value is restored when the object of this class
 * goes out of scope.
 * This class is not intended to be used directly, because its usage is cumbersome.
 * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
 */
class ScopedFlagOverride {
public:
    ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
          : mInitialValue(read()), mWriteValue(write) {
        mWriteValue(value);
    }
    ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
private:
    const bool mInitialValue;
    std::function<void(bool)> mWriteValue;
};
typedef bool (*readFlagValueFunction)();
typedef void (*writeFlagValueFunction)(bool);
/**
 * Use this macro to locally override a flag value.
 * Example usage:
 *    SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
 * Note: this works by creating a local variable in your current scope. Don't call this twice for
 * the same flag, because the variable names will clash!
 */
#define SCOPED_FLAG_OVERRIDE(NAME, VALUE)                                  \
    readFlagValueFunction read##NAME = com::android::input::flags::NAME;   \
    writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
    ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
} // namespace
// --- InputDispatcherTest ---
+29 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <MultiTouchInputMapper.h>
#include <NotifyArgsBuilders.h>
#include <PeripheralController.h>
#include <ScopedFlagOverride.h>
#include <SingleTouchInputMapper.h>
#include <TestEventMatchers.h>
#include <TestInputListener.h>
@@ -4526,6 +4527,10 @@ TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {

    NotifyMotionArgs motionArgs;

    // Hold down the mouse button for the duration of the test, since the mouse tools require
    // the button to be pressed to make sure they are not hovering.
    processKey(mapper, BTN_MOUSE, 1);

    // default tool type is finger
    processDown(mapper, 100, 200);
    processSync(mapper);
@@ -4533,6 +4538,9 @@ TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
    ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);

    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)));

    // eraser
    processKey(mapper, BTN_TOOL_RUBBER, 1);
    processSync(mapper);
@@ -7175,6 +7183,10 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {

    NotifyMotionArgs motionArgs;

    // Hold down the mouse button for the duration of the test, since the mouse tools require
    // the button to be pressed to make sure they are not hovering.
    processKey(mapper, BTN_MOUSE, 1);

    // default tool type is finger
    processId(mapper, 1);
    processPosition(mapper, 100, 200);
@@ -7183,6 +7195,9 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
    ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);

    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)));

    // eraser
    processKey(mapper, BTN_TOOL_RUBBER, 1);
    processSync(mapper);
@@ -7520,6 +7535,7 @@ TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
}

TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
    SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, true);
    prepareSecondaryDisplay(ViewportType::EXTERNAL);

    prepareDisplay(ui::ROTATION_0);
@@ -7532,9 +7548,9 @@ TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
    processPosition(mapper, 100, 100);
    processSync(mapper);

    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
    ASSERT_EQ(DISPLAY_ID, motionArgs.displayId);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDisplayId(DISPLAY_ID),
                  WithSource(AINPUT_SOURCE_MOUSE), WithToolType(ToolType::FINGER))));
}

/**
@@ -8604,6 +8620,8 @@ protected:
 * fingers start to move downwards, the gesture should be swipe.
 */
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
    SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);

    // The min freeform gesture width is 25units/mm x 30mm = 750
    // which is greater than fraction of the diagnal length of the touchpad (349).
    // Thus, MaxSwipWidth is 750.
@@ -8664,6 +8682,8 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
 * the gesture should be swipe.
 */
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
    SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);

    // The min freeform gesture width is 5units/mm x 30mm = 150
    // which is greater than fraction of the diagnal length of the touchpad (349).
    // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
@@ -8723,6 +8743,8 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe)
 * freeform gestures after two fingers start to move downwards.
 */
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
    SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);

    preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
    MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();

@@ -8818,6 +8840,8 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
}

TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
    SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);

    preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
    MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
    NotifyMotionArgs motionArgs;
@@ -8864,6 +8888,8 @@ TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
}

TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
    SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);

    preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
    mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
    MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Loading