Skip to content

Commit 869b89d

Browse files
committed
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
1 parent 5ce9acd commit 869b89d

7 files changed

Lines changed: 224 additions & 42 deletions

File tree

libs/input/input_flags.aconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,16 @@ flag {
187187
is_fixed_read_only: true
188188
}
189189

190+
flag {
191+
name: "disable_touch_input_mapper_pointer_usage"
192+
namespace: "input"
193+
description: "Disable the PointerUsage concept in TouchInputMapper since the old touchpad stack is no longer used."
194+
bug: "281840344"
195+
metadata {
196+
purpose: PURPOSE_BUGFIX
197+
}
198+
}
199+
190200
flag {
191201
name: "keyboard_repeat_keys"
192202
namespace: "input"

services/inputflinger/reader/mapper/TouchInputMapper.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include <android-base/stringprintf.h>
3232
#include <android/input.h>
33+
#include <com_android_input_flags.h>
3334
#include <ftl/enum.h>
3435
#include <input/PrintTools.h>
3536
#include <input/PropertyMap.h>
@@ -47,6 +48,8 @@
4748

4849
namespace android {
4950

51+
namespace input_flags = com::android::input::flags;
52+
5053
// --- Constants ---
5154

5255
// 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
15751578
mLastCookedState.buttonState, mCurrentCookedState.buttonState);
15761579

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

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

2260+
bool isHovering = in.isHovering;
2261+
2262+
// A tool MOUSE pointer is only down/touching when a mouse button is pressed.
2263+
if (input_flags::disable_touch_input_mapper_pointer_usage() &&
2264+
in.toolType == ToolType::MOUSE &&
2265+
!mCurrentRawState.rawPointerData.canceledIdBits.hasBit(in.id)) {
2266+
if (isPointerDown(mCurrentRawState.buttonState)) {
2267+
isHovering = false;
2268+
mCurrentCookedState.cookedPointerData.touchingIdBits.markBit(in.id);
2269+
mCurrentCookedState.cookedPointerData.hoveringIdBits.clearBit(in.id);
2270+
} else {
2271+
isHovering = true;
2272+
mCurrentCookedState.cookedPointerData.touchingIdBits.clearBit(in.id);
2273+
mCurrentCookedState.cookedPointerData.hoveringIdBits.markBit(in.id);
2274+
}
2275+
}
2276+
22542277
// Size
22552278
float touchMajor, touchMinor, toolMajor, toolMinor, size;
22562279
switch (mCalibration.sizeCalibration) {
@@ -2340,7 +2363,7 @@ void TouchInputMapper::cookPointerData() {
23402363
pressure = in.pressure * mPressureScale;
23412364
break;
23422365
default:
2343-
pressure = in.isHovering ? 0 : 1;
2366+
pressure = isHovering ? 0 : 1;
23442367
break;
23452368
}
23462369

@@ -3697,7 +3720,10 @@ NotifyMotionArgs TouchInputMapper::dispatchMotion(
36973720
float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
36983721
float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
36993722
if (mDeviceMode == DeviceMode::POINTER) {
3700-
xCursorPosition = yCursorPosition = 0.f;
3723+
ALOGW_IF(pointerCount != 1,
3724+
"Only single pointer events are fully supported in POINTER mode");
3725+
xCursorPosition = pointerCoords[0].getX();
3726+
yCursorPosition = pointerCoords[0].getY();
37013727
}
37023728
const DeviceId deviceId = getDeviceId();
37033729
std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();

services/inputflinger/reader/mapper/TouchInputMapper.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class TouchInputMapper : public InputMapper {
215215
DISABLED, // input is disabled
216216
DIRECT, // direct mapping (touchscreen)
217217
NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
218-
POINTER, // pointer mapping (e.g. uncaptured touchpad, drawing tablet)
218+
POINTER, // pointer mapping (e.g. absolute mouse, drawing tablet)
219219

220220
ftl_last = POINTER
221221
};
@@ -234,6 +234,9 @@ class TouchInputMapper : public InputMapper {
234234
ftl_last = POINTER
235235
};
236236

237+
// TouchInputMapper will configure devices with INPUT_PROP_DIRECT as
238+
// DeviceType::TOUCH_SCREEN, and will otherwise use DeviceType::POINTER by default.
239+
// This can be overridden by IDC files, using the `touch.deviceType` config.
237240
DeviceType deviceType;
238241
bool hasAssociatedDisplay;
239242
bool associatedDisplayIsExternal;

services/inputflinger/tests/InputDispatcher_test.cpp

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "FakeInputDispatcherPolicy.h"
2020
#include "FakeInputTracingBackend.h"
2121
#include "FakeWindows.h"
22+
#include "ScopedFlagOverride.h"
2223
#include "TestEventMatchers.h"
2324

2425
#include <NotifyArgsBuilders.h>
@@ -138,40 +139,6 @@ static KeyEvent getTestKeyEvent() {
138139
return event;
139140
}
140141

141-
/**
142-
* Provide a local override for a flag value. The value is restored when the object of this class
143-
* goes out of scope.
144-
* This class is not intended to be used directly, because its usage is cumbersome.
145-
* Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
146-
*/
147-
class ScopedFlagOverride {
148-
public:
149-
ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
150-
: mInitialValue(read()), mWriteValue(write) {
151-
mWriteValue(value);
152-
}
153-
~ScopedFlagOverride() { mWriteValue(mInitialValue); }
154-
155-
private:
156-
const bool mInitialValue;
157-
std::function<void(bool)> mWriteValue;
158-
};
159-
160-
typedef bool (*readFlagValueFunction)();
161-
typedef void (*writeFlagValueFunction)(bool);
162-
163-
/**
164-
* Use this macro to locally override a flag value.
165-
* Example usage:
166-
* SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
167-
* Note: this works by creating a local variable in your current scope. Don't call this twice for
168-
* the same flag, because the variable names will clash!
169-
*/
170-
#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
171-
readFlagValueFunction read##NAME = com::android::input::flags::NAME; \
172-
writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
173-
ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
174-
175142
} // namespace
176143

177144
// --- InputDispatcherTest ---

services/inputflinger/tests/InputReader_test.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <MultiTouchInputMapper.h>
2929
#include <NotifyArgsBuilders.h>
3030
#include <PeripheralController.h>
31+
#include <ScopedFlagOverride.h>
3132
#include <SingleTouchInputMapper.h>
3233
#include <TestEventMatchers.h>
3334
#include <TestInputListener.h>
@@ -4526,13 +4527,20 @@ TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
45264527

45274528
NotifyMotionArgs motionArgs;
45284529

4530+
// Hold down the mouse button for the duration of the test, since the mouse tools require
4531+
// the button to be pressed to make sure they are not hovering.
4532+
processKey(mapper, BTN_MOUSE, 1);
4533+
45294534
// default tool type is finger
45304535
processDown(mapper, 100, 200);
45314536
processSync(mapper);
45324537
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
45334538
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
45344539
ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
45354540

4541+
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
4542+
WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)));
4543+
45364544
// eraser
45374545
processKey(mapper, BTN_TOOL_RUBBER, 1);
45384546
processSync(mapper);
@@ -7175,6 +7183,10 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
71757183

71767184
NotifyMotionArgs motionArgs;
71777185

7186+
// Hold down the mouse button for the duration of the test, since the mouse tools require
7187+
// the button to be pressed to make sure they are not hovering.
7188+
processKey(mapper, BTN_MOUSE, 1);
7189+
71787190
// default tool type is finger
71797191
processId(mapper, 1);
71807192
processPosition(mapper, 100, 200);
@@ -7183,6 +7195,9 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
71837195
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
71847196
ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
71857197

7198+
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7199+
WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)));
7200+
71867201
// eraser
71877202
processKey(mapper, BTN_TOOL_RUBBER, 1);
71887203
processSync(mapper);
@@ -7520,6 +7535,7 @@ TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
75207535
}
75217536

75227537
TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
7538+
SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, true);
75237539
prepareSecondaryDisplay(ViewportType::EXTERNAL);
75247540

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

7535-
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7536-
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
7537-
ASSERT_EQ(DISPLAY_ID, motionArgs.displayId);
7551+
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7552+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDisplayId(DISPLAY_ID),
7553+
WithSource(AINPUT_SOURCE_MOUSE), WithToolType(ToolType::FINGER))));
75387554
}
75397555

75407556
/**
@@ -8604,6 +8620,8 @@ class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
86048620
* fingers start to move downwards, the gesture should be swipe.
86058621
*/
86068622
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
8623+
SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
8624+
86078625
// The min freeform gesture width is 25units/mm x 30mm = 750
86088626
// which is greater than fraction of the diagnal length of the touchpad (349).
86098627
// Thus, MaxSwipWidth is 750.
@@ -8664,6 +8682,8 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
86648682
* the gesture should be swipe.
86658683
*/
86668684
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
8685+
SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
8686+
86678687
// The min freeform gesture width is 5units/mm x 30mm = 150
86688688
// which is greater than fraction of the diagnal length of the touchpad (349).
86698689
// Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
@@ -8723,6 +8743,8 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe)
87238743
* freeform gestures after two fingers start to move downwards.
87248744
*/
87258745
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
8746+
SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
8747+
87268748
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
87278749
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
87288750

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

88208842
TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
8843+
SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
8844+
88218845
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
88228846
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
88238847
NotifyMotionArgs motionArgs;
@@ -8864,6 +8888,8 @@ TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
88648888
}
88658889

88668890
TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
8891+
SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
8892+
88678893
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
88688894
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
88698895
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();

services/inputflinger/tests/MultiTouchInputMapper_test.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@
2323

2424
#include "InputMapperTest.h"
2525
#include "InterfaceMocks.h"
26+
#include "ScopedFlagOverride.h"
2627
#include "TestEventMatchers.h"
2728

2829
#define TAG "MultiTouchpadInputMapperUnit_test"
2930

3031
namespace android {
3132

3233
using testing::_;
34+
using testing::AllOf;
3335
using testing::IsEmpty;
3436
using testing::Return;
3537
using testing::SetArgPointee;
@@ -266,4 +268,94 @@ TEST_F(MultiTouchInputMapperUnitTest, MultiFingerGestureWithUnexpectedReset) {
266268
VariantWith<NotifyMotionArgs>(WithMotionAction(AMOTION_EVENT_ACTION_UP))));
267269
}
268270

271+
class MultiTouchInputMapperPointerModeUnitTest : public MultiTouchInputMapperUnitTest {
272+
protected:
273+
void SetUp() override {
274+
MultiTouchInputMapperUnitTest::SetUp();
275+
276+
// TouchInputMapper goes into POINTER mode whenever INPUT_PROP_DIRECT is not set.
277+
EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, INPUT_PROP_DIRECT))
278+
.WillRepeatedly(Return(false));
279+
280+
mMapper = createInputMapper<MultiTouchInputMapper>(*mDeviceContext,
281+
mFakePolicy->getReaderConfiguration());
282+
}
283+
};
284+
285+
TEST_F(MultiTouchInputMapperPointerModeUnitTest, MouseToolOnlyDownWhenMouseButtonsAreDown) {
286+
SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, true);
287+
288+
std::list<NotifyArgs> args;
289+
290+
// Set the tool type to mouse.
291+
args += processKey(BTN_TOOL_MOUSE, 1);
292+
293+
args += processPosition(100, 100);
294+
args += processId(1);
295+
ASSERT_THAT(args, IsEmpty());
296+
297+
args = processSync();
298+
ASSERT_THAT(args,
299+
ElementsAre(VariantWith<NotifyMotionArgs>(
300+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
301+
WithToolType(ToolType::MOUSE))),
302+
VariantWith<NotifyMotionArgs>(
303+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
304+
WithToolType(ToolType::MOUSE)))));
305+
306+
// Setting BTN_TOUCH does not make a mouse pointer go down.
307+
args = processKey(BTN_TOUCH, 1);
308+
args += processSync();
309+
ASSERT_THAT(args,
310+
ElementsAre(VariantWith<NotifyMotionArgs>(
311+
WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))));
312+
313+
// The mouse button is pressed, so the mouse goes down.
314+
args = processKey(BTN_MOUSE, 1);
315+
args += processSync();
316+
ASSERT_THAT(args,
317+
ElementsAre(VariantWith<NotifyMotionArgs>(
318+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
319+
WithToolType(ToolType::MOUSE))),
320+
VariantWith<NotifyMotionArgs>(
321+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
322+
WithToolType(ToolType::MOUSE),
323+
WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))),
324+
VariantWith<NotifyMotionArgs>(
325+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
326+
WithToolType(ToolType::MOUSE),
327+
WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
328+
WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY)))));
329+
330+
// The mouse button is released, so the mouse starts hovering.
331+
args = processKey(BTN_MOUSE, 0);
332+
args += processSync();
333+
ASSERT_THAT(args,
334+
ElementsAre(VariantWith<NotifyMotionArgs>(
335+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
336+
WithButtonState(0), WithToolType(ToolType::MOUSE),
337+
WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY))),
338+
VariantWith<NotifyMotionArgs>(
339+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
340+
WithToolType(ToolType::MOUSE), WithButtonState(0))),
341+
VariantWith<NotifyMotionArgs>(
342+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
343+
WithToolType(ToolType::MOUSE))),
344+
VariantWith<NotifyMotionArgs>(
345+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
346+
WithToolType(ToolType::MOUSE)))));
347+
348+
// Change the tool type so that it is no longer a mouse.
349+
// The default tool type is finger, and the finger is already down.
350+
args = processKey(BTN_TOOL_MOUSE, 0);
351+
args += processSync();
352+
ASSERT_THAT(args,
353+
ElementsAre(VariantWith<NotifyMotionArgs>(
354+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
355+
WithToolType(ToolType::MOUSE))),
356+
VariantWith<NotifyMotionArgs>(
357+
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
358+
WithToolType(ToolType::FINGER)))));
359+
}
360+
269361
} // namespace android

0 commit comments

Comments
 (0)