Skip to content

Commit ea395bf

Browse files
committed
Add tests for AndroidInputEventProtoConverter::toProtoMotionEvent
We use mocked classes as stand-ins for the Perfetto proto classes. Since Perfetto uses ProtoZero where the generated C++ classes do not allow for readback, they cannot be used directly in the tests. The generated proto classes' methods are also non-virtual, so we cannot override them in tests. We are therefore using a templating strategy to provide separte mock implementations of the proto classes for testing. This has the additional benefits of: - giving a build error if a new unmocked method is used in the test, reminding us to add tests for newly traced fields; and - allowing us to use strict mocks to easily enforce that more information is not traced compared to what is expected by the tests. Bug: 391468016 Test: Presubmit Flag: TEST_ONLY Change-Id: I73c090e86b30eaed416fc8d2b05a162832d4ec00
1 parent 943fb05 commit ea395bf

3 files changed

Lines changed: 263 additions & 1 deletion

File tree

services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct TracedMotionEvent {
7070
uint32_t policyFlags;
7171
int32_t deviceId;
7272
uint32_t source;
73-
ui::LogicalDisplayId displayId;
73+
ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
7474
int32_t action;
7575
int32_t actionButton;
7676
int32_t flags;

services/inputflinger/tests/Android.bp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ cc_test {
4848
],
4949
srcs: [
5050
":inputdispatcher_common_test_sources",
51+
"AndroidInputEventProtoConverter_test.cpp",
5152
"AnrTracker_test.cpp",
5253
"CapturedTouchpadEventConverter_test.cpp",
5354
"CursorInputMapper_test.cpp",
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "../dispatcher/trace/AndroidInputEventProtoConverter.h"
18+
19+
#include <gmock/gmock.h>
20+
#include <gtest/gtest.h>
21+
22+
namespace android::inputdispatcher::trace {
23+
24+
namespace {
25+
26+
using testing::Return, testing::_;
27+
28+
class MockProtoAxisValue {
29+
public:
30+
MOCK_METHOD(void, set_axis, (int32_t));
31+
MOCK_METHOD(void, set_value, (float));
32+
};
33+
34+
class MockProtoPointer {
35+
public:
36+
MOCK_METHOD(void, set_pointer_id, (uint32_t));
37+
MOCK_METHOD(void, set_tool_type, (int32_t));
38+
MOCK_METHOD(MockProtoAxisValue*, add_axis_value, ());
39+
};
40+
41+
class MockProtoMotion {
42+
public:
43+
MOCK_METHOD(void, set_event_id, (uint32_t));
44+
MOCK_METHOD(void, set_event_time_nanos, (int64_t));
45+
MOCK_METHOD(void, set_down_time_nanos, (int64_t));
46+
MOCK_METHOD(void, set_source, (uint32_t));
47+
MOCK_METHOD(void, set_action, (int32_t));
48+
MOCK_METHOD(void, set_device_id, (uint32_t));
49+
MOCK_METHOD(void, set_display_id, (uint32_t));
50+
MOCK_METHOD(void, set_classification, (int32_t));
51+
MOCK_METHOD(void, set_flags, (uint32_t));
52+
MOCK_METHOD(void, set_policy_flags, (uint32_t));
53+
MOCK_METHOD(void, set_button_state, (uint32_t));
54+
MOCK_METHOD(void, set_action_button, (uint32_t));
55+
MOCK_METHOD(void, set_cursor_position_x, (float));
56+
MOCK_METHOD(void, set_cursor_position_y, (float));
57+
MOCK_METHOD(void, set_meta_state, (uint32_t));
58+
MOCK_METHOD(void, set_precision_x, (float));
59+
MOCK_METHOD(void, set_precision_y, (float));
60+
MOCK_METHOD(MockProtoPointer*, add_pointer, ());
61+
};
62+
63+
using TestProtoConverter = AndroidInputEventProtoConverter<MockProtoMotion, proto::AndroidKeyEvent,
64+
proto::AndroidWindowInputDispatchEvent,
65+
proto::AndroidInputEventConfig::Decoder>;
66+
67+
TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent) {
68+
TracedMotionEvent event{};
69+
event.id = 1;
70+
event.eventTime = 2;
71+
event.downTime = 3;
72+
event.source = AINPUT_SOURCE_MOUSE;
73+
event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS;
74+
event.deviceId = 4;
75+
event.displayId = ui::LogicalDisplayId(5);
76+
event.classification = MotionClassification::PINCH;
77+
event.flags = 6;
78+
event.policyFlags = 7;
79+
event.buttonState = 8;
80+
event.actionButton = 9;
81+
event.xCursorPosition = 10.0f;
82+
event.yCursorPosition = 11.0f;
83+
event.metaState = 12;
84+
event.xPrecision = 13.0f;
85+
event.yPrecision = 14.0f;
86+
event.pointerProperties.emplace_back(PointerProperties{
87+
.id = 15,
88+
.toolType = ToolType::MOUSE,
89+
});
90+
event.pointerProperties.emplace_back(PointerProperties{
91+
.id = 16,
92+
.toolType = ToolType::FINGER,
93+
});
94+
event.pointerCoords.emplace_back();
95+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 17.0f);
96+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 18.0f);
97+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 19.0f);
98+
event.pointerCoords.emplace_back();
99+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 20.0f);
100+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 21.0f);
101+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22.0f);
102+
103+
testing::StrictMock<MockProtoMotion> proto;
104+
testing::StrictMock<MockProtoPointer> pointer1;
105+
testing::StrictMock<MockProtoPointer> pointer2;
106+
testing::StrictMock<MockProtoAxisValue> axisValue1;
107+
testing::StrictMock<MockProtoAxisValue> axisValue2;
108+
testing::StrictMock<MockProtoAxisValue> axisValue3;
109+
testing::StrictMock<MockProtoAxisValue> axisValue4;
110+
testing::StrictMock<MockProtoAxisValue> axisValue5;
111+
testing::StrictMock<MockProtoAxisValue> axisValue6;
112+
113+
EXPECT_CALL(proto, set_event_id(1));
114+
EXPECT_CALL(proto, set_event_time_nanos(2));
115+
EXPECT_CALL(proto, set_down_time_nanos(3));
116+
EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE));
117+
EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS));
118+
EXPECT_CALL(proto, set_device_id(4));
119+
EXPECT_CALL(proto, set_display_id(5));
120+
EXPECT_CALL(proto, set_classification(AMOTION_EVENT_CLASSIFICATION_PINCH));
121+
EXPECT_CALL(proto, set_flags(6));
122+
EXPECT_CALL(proto, set_policy_flags(7));
123+
EXPECT_CALL(proto, set_button_state(8));
124+
EXPECT_CALL(proto, set_action_button(9));
125+
EXPECT_CALL(proto, set_cursor_position_x(10.0f));
126+
EXPECT_CALL(proto, set_cursor_position_y(11.0f));
127+
EXPECT_CALL(proto, set_meta_state(12));
128+
EXPECT_CALL(proto, set_precision_x(13.0f));
129+
EXPECT_CALL(proto, set_precision_y(14.0f));
130+
131+
EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2));
132+
133+
EXPECT_CALL(pointer1, set_pointer_id(15));
134+
EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE));
135+
EXPECT_CALL(pointer1, add_axis_value())
136+
.WillOnce(Return(&axisValue1))
137+
.WillOnce(Return(&axisValue2))
138+
.WillOnce(Return(&axisValue3));
139+
EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X));
140+
EXPECT_CALL(axisValue1, set_value(17.0f));
141+
EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y));
142+
EXPECT_CALL(axisValue2, set_value(18.0f));
143+
EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
144+
EXPECT_CALL(axisValue3, set_value(19.0f));
145+
146+
EXPECT_CALL(pointer2, set_pointer_id(16));
147+
EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER));
148+
EXPECT_CALL(pointer2, add_axis_value())
149+
.WillOnce(Return(&axisValue4))
150+
.WillOnce(Return(&axisValue5))
151+
.WillOnce(Return(&axisValue6));
152+
EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_X));
153+
EXPECT_CALL(axisValue4, set_value(20.0f));
154+
EXPECT_CALL(axisValue5, set_axis(AMOTION_EVENT_AXIS_Y));
155+
EXPECT_CALL(axisValue5, set_value(21.0f));
156+
EXPECT_CALL(axisValue6, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
157+
EXPECT_CALL(axisValue6, set_value(22.0f));
158+
159+
TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/false);
160+
}
161+
162+
TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent_Redacted) {
163+
TracedMotionEvent event{};
164+
event.id = 1;
165+
event.eventTime = 2;
166+
event.downTime = 3;
167+
event.source = AINPUT_SOURCE_MOUSE;
168+
event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS;
169+
event.deviceId = 4;
170+
event.displayId = ui::LogicalDisplayId(5);
171+
event.classification = MotionClassification::PINCH;
172+
event.flags = 6;
173+
event.policyFlags = 7;
174+
event.buttonState = 8;
175+
event.actionButton = 9;
176+
event.xCursorPosition = 10.0f;
177+
event.yCursorPosition = 11.0f;
178+
event.metaState = 12;
179+
event.xPrecision = 13.0f;
180+
event.yPrecision = 14.0f;
181+
event.pointerProperties.emplace_back(PointerProperties{
182+
.id = 15,
183+
.toolType = ToolType::MOUSE,
184+
});
185+
event.pointerProperties.emplace_back(PointerProperties{
186+
.id = 16,
187+
.toolType = ToolType::FINGER,
188+
});
189+
event.pointerCoords.emplace_back();
190+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 17.0f);
191+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 18.0f);
192+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 19.0f);
193+
event.pointerCoords.emplace_back();
194+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 20.0f);
195+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 21.0f);
196+
event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22.0f);
197+
198+
testing::StrictMock<MockProtoMotion> proto;
199+
testing::StrictMock<MockProtoPointer> pointer1;
200+
testing::StrictMock<MockProtoPointer> pointer2;
201+
testing::StrictMock<MockProtoAxisValue> axisValue1;
202+
testing::StrictMock<MockProtoAxisValue> axisValue2;
203+
testing::StrictMock<MockProtoAxisValue> axisValue3;
204+
testing::StrictMock<MockProtoAxisValue> axisValue4;
205+
testing::StrictMock<MockProtoAxisValue> axisValue5;
206+
testing::StrictMock<MockProtoAxisValue> axisValue6;
207+
208+
EXPECT_CALL(proto, set_event_id(1));
209+
EXPECT_CALL(proto, set_event_time_nanos(2));
210+
EXPECT_CALL(proto, set_down_time_nanos(3));
211+
EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE));
212+
EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS));
213+
EXPECT_CALL(proto, set_device_id(4));
214+
EXPECT_CALL(proto, set_display_id(5));
215+
EXPECT_CALL(proto, set_classification(AMOTION_EVENT_CLASSIFICATION_PINCH));
216+
EXPECT_CALL(proto, set_flags(6));
217+
EXPECT_CALL(proto, set_policy_flags(7));
218+
EXPECT_CALL(proto, set_button_state(8));
219+
EXPECT_CALL(proto, set_action_button(9));
220+
221+
EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2));
222+
223+
EXPECT_CALL(pointer1, set_pointer_id(15));
224+
EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE));
225+
EXPECT_CALL(pointer1, add_axis_value())
226+
.WillOnce(Return(&axisValue1))
227+
.WillOnce(Return(&axisValue2))
228+
.WillOnce(Return(&axisValue3));
229+
EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X));
230+
EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y));
231+
EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
232+
233+
EXPECT_CALL(pointer2, set_pointer_id(16));
234+
EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER));
235+
EXPECT_CALL(pointer2, add_axis_value())
236+
.WillOnce(Return(&axisValue4))
237+
.WillOnce(Return(&axisValue5))
238+
.WillOnce(Return(&axisValue6));
239+
EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_X));
240+
EXPECT_CALL(axisValue5, set_axis(AMOTION_EVENT_AXIS_Y));
241+
EXPECT_CALL(axisValue6, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
242+
243+
// Redacted fields
244+
EXPECT_CALL(proto, set_meta_state(_)).Times(0);
245+
EXPECT_CALL(proto, set_cursor_position_x(_)).Times(0);
246+
EXPECT_CALL(proto, set_cursor_position_y(_)).Times(0);
247+
EXPECT_CALL(proto, set_precision_x(_)).Times(0);
248+
EXPECT_CALL(proto, set_precision_y(_)).Times(0);
249+
EXPECT_CALL(axisValue1, set_value(_)).Times(0);
250+
EXPECT_CALL(axisValue2, set_value(_)).Times(0);
251+
EXPECT_CALL(axisValue3, set_value(_)).Times(0);
252+
EXPECT_CALL(axisValue4, set_value(_)).Times(0);
253+
EXPECT_CALL(axisValue5, set_value(_)).Times(0);
254+
EXPECT_CALL(axisValue6, set_value(_)).Times(0);
255+
256+
TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/true);
257+
}
258+
259+
} // namespace
260+
261+
} // namespace android::inputdispatcher::trace

0 commit comments

Comments
 (0)