diff options
3 files changed, 203 insertions, 8 deletions
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h index eb33e2b894..c19d278370 100644 --- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h +++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h @@ -41,6 +41,16 @@ const impl::TraceConfig CONFIG_TRACE_ALL{ .matchImeConnectionActive = {}}}, }; +template <typename Pointer> +void writeAxisValue(Pointer* pointer, int32_t axis, float value, bool isRedacted) { + auto* axisEntry = pointer->add_axis_value(); + axisEntry->set_axis(axis); + + if (!isRedacted) { + axisEntry->set_value(value); + } +} + } // namespace internal /** @@ -85,15 +95,21 @@ public: const auto& coords = event.pointerCoords[i]; auto bits = BitSet64(coords.bits); - for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) { - const auto axis = bits.clearFirstMarkedBit(); - auto axisEntry = pointer->add_axis_value(); - axisEntry->set_axis(axis); - if (!isRedacted) { - axisEntry->set_value(coords.values[axisIndex]); + if (isFromSource(event.source, AINPUT_SOURCE_CLASS_POINTER)) { + // Always include the X and Y axes for pointer events, since the + // bits will not be marked if the value is 0. + for (const auto axis : {AMOTION_EVENT_AXIS_X, AMOTION_EVENT_AXIS_Y}) { + if (!bits.hasBit(axis)) { + internal::writeAxisValue(pointer, axis, 0.0f, isRedacted); + } } } + + for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) { + const auto axis = bits.clearFirstMarkedBit(); + internal::writeAxisValue(pointer, axis, coords.values[axisIndex], isRedacted); + } } } diff --git a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h index 823f8a5882..6ea21c819c 100644 --- a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h +++ b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h @@ -50,7 +50,7 @@ struct TracedKeyEvent { uint32_t policyFlags; int32_t deviceId; uint32_t source; - ui::LogicalDisplayId displayId; + ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID; int32_t action; int32_t keyCode; int32_t scanCode; diff --git a/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp b/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp index 414da66cd2..f9159c1dd8 100644 --- a/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp +++ b/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp @@ -60,7 +60,24 @@ public: MOCK_METHOD(MockProtoPointer*, add_pointer, ()); }; -using TestProtoConverter = AndroidInputEventProtoConverter<MockProtoMotion, proto::AndroidKeyEvent, +class MockProtoKey { +public: + MOCK_METHOD(void, set_event_id, (uint32_t)); + MOCK_METHOD(void, set_event_time_nanos, (int64_t)); + MOCK_METHOD(void, set_down_time_nanos, (int64_t)); + MOCK_METHOD(void, set_source, (uint32_t)); + MOCK_METHOD(void, set_action, (int32_t)); + MOCK_METHOD(void, set_device_id, (uint32_t)); + MOCK_METHOD(void, set_display_id, (uint32_t)); + MOCK_METHOD(void, set_repeat_count, (uint32_t)); + MOCK_METHOD(void, set_flags, (uint32_t)); + MOCK_METHOD(void, set_policy_flags, (uint32_t)); + MOCK_METHOD(void, set_key_code, (uint32_t)); + MOCK_METHOD(void, set_scan_code, (uint32_t)); + MOCK_METHOD(void, set_meta_state, (uint32_t)); +}; + +using TestProtoConverter = AndroidInputEventProtoConverter<MockProtoMotion, MockProtoKey, proto::AndroidWindowInputDispatchEvent, proto::AndroidInputEventConfig::Decoder>; @@ -256,6 +273,168 @@ TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent_Redacted) { TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/true); } +// Test any special handling for zero values for pointer events. +TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent_ZeroValues) { + TracedMotionEvent event{}; + event.id = 0; + event.eventTime = 0; + event.downTime = 0; + event.source = AINPUT_SOURCE_MOUSE; + event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS; + event.deviceId = 0; + event.displayId = ui::LogicalDisplayId(0); + event.classification = {}; + event.flags = 0; + event.policyFlags = 0; + event.buttonState = 0; + event.actionButton = 0; + event.xCursorPosition = 0.0f; + event.yCursorPosition = 0.0f; + event.metaState = 0; + event.xPrecision = 0.0f; + event.yPrecision = 0.0f; + event.pointerProperties.emplace_back(PointerProperties{ + .id = 0, + .toolType = ToolType::MOUSE, + }); + event.pointerProperties.emplace_back(PointerProperties{ + .id = 1, + .toolType = ToolType::FINGER, + }); + // Zero values for x and y axes are always traced for pointer events. + // However, zero values for other axes may not necessarily be traced. + event.pointerCoords.emplace_back(); + event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 0.0f); + event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 1.0f); + event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f); + event.pointerCoords.emplace_back(); + event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 0.0f); + event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 0.0f); + event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f); + + testing::StrictMock<MockProtoMotion> proto; + testing::StrictMock<MockProtoPointer> pointer1; + testing::StrictMock<MockProtoPointer> pointer2; + testing::StrictMock<MockProtoAxisValue> axisValue1; + testing::StrictMock<MockProtoAxisValue> axisValue2; + testing::StrictMock<MockProtoAxisValue> axisValue3; + testing::StrictMock<MockProtoAxisValue> axisValue4; + + EXPECT_CALL(proto, set_event_id(0)); + EXPECT_CALL(proto, set_event_time_nanos(0)); + EXPECT_CALL(proto, set_down_time_nanos(0)); + EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE)); + EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS)); + EXPECT_CALL(proto, set_device_id(0)); + EXPECT_CALL(proto, set_display_id(0)); + EXPECT_CALL(proto, set_classification(0)); + EXPECT_CALL(proto, set_flags(0)); + EXPECT_CALL(proto, set_policy_flags(0)); + EXPECT_CALL(proto, set_button_state(0)); + EXPECT_CALL(proto, set_action_button(0)); + EXPECT_CALL(proto, set_cursor_position_x(0.0f)); + EXPECT_CALL(proto, set_cursor_position_y(0.0f)); + EXPECT_CALL(proto, set_meta_state(0)); + EXPECT_CALL(proto, set_precision_x(0.0f)); + EXPECT_CALL(proto, set_precision_y(0.0f)); + + EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2)); + + EXPECT_CALL(pointer1, set_pointer_id(0)); + EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE)); + EXPECT_CALL(pointer1, add_axis_value()) + .WillOnce(Return(&axisValue1)) + .WillOnce(Return(&axisValue2)); + EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X)); + EXPECT_CALL(axisValue1, set_value(0.0f)); + EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y)); + EXPECT_CALL(axisValue2, set_value(1.0f)); + + EXPECT_CALL(pointer2, set_pointer_id(1)); + EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER)); + EXPECT_CALL(pointer2, add_axis_value()) + .WillOnce(Return(&axisValue3)) + .WillOnce(Return(&axisValue4)); + EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_X)); + EXPECT_CALL(axisValue3, set_value(0.0f)); + EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_Y)); + EXPECT_CALL(axisValue4, set_value(0.0f)); + + TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/false); +} + +TEST(AndroidInputEventProtoConverterTest, ToProtoKeyEvent) { + TracedKeyEvent event{}; + event.id = 1; + event.eventTime = 2; + event.downTime = 3; + event.source = AINPUT_SOURCE_KEYBOARD; + event.action = AKEY_EVENT_ACTION_DOWN; + event.deviceId = 4; + event.displayId = ui::LogicalDisplayId(5); + event.repeatCount = 6; + event.flags = 7; + event.policyFlags = 8; + event.keyCode = 9; + event.scanCode = 10; + event.metaState = 11; + + testing::StrictMock<MockProtoKey> proto; + + EXPECT_CALL(proto, set_event_id(1)); + EXPECT_CALL(proto, set_event_time_nanos(2)); + EXPECT_CALL(proto, set_down_time_nanos(3)); + EXPECT_CALL(proto, set_source(AINPUT_SOURCE_KEYBOARD)); + EXPECT_CALL(proto, set_action(AKEY_EVENT_ACTION_DOWN)); + EXPECT_CALL(proto, set_device_id(4)); + EXPECT_CALL(proto, set_display_id(5)); + EXPECT_CALL(proto, set_repeat_count(6)); + EXPECT_CALL(proto, set_flags(7)); + EXPECT_CALL(proto, set_policy_flags(8)); + EXPECT_CALL(proto, set_key_code(9)); + EXPECT_CALL(proto, set_scan_code(10)); + EXPECT_CALL(proto, set_meta_state(11)); + + TestProtoConverter::toProtoKeyEvent(event, proto, /*isRedacted=*/false); +} + +TEST(AndroidInputEventProtoConverterTest, ToProtoKeyEvent_Redacted) { + TracedKeyEvent event{}; + event.id = 1; + event.eventTime = 2; + event.downTime = 3; + event.source = AINPUT_SOURCE_KEYBOARD; + event.action = AKEY_EVENT_ACTION_DOWN; + event.deviceId = 4; + event.displayId = ui::LogicalDisplayId(5); + event.repeatCount = 6; + event.flags = 7; + event.policyFlags = 8; + event.keyCode = 9; + event.scanCode = 10; + event.metaState = 11; + + testing::StrictMock<MockProtoKey> proto; + + EXPECT_CALL(proto, set_event_id(1)); + EXPECT_CALL(proto, set_event_time_nanos(2)); + EXPECT_CALL(proto, set_down_time_nanos(3)); + EXPECT_CALL(proto, set_source(AINPUT_SOURCE_KEYBOARD)); + EXPECT_CALL(proto, set_action(AKEY_EVENT_ACTION_DOWN)); + EXPECT_CALL(proto, set_device_id(4)); + EXPECT_CALL(proto, set_display_id(5)); + EXPECT_CALL(proto, set_repeat_count(6)); + EXPECT_CALL(proto, set_flags(7)); + EXPECT_CALL(proto, set_policy_flags(8)); + + // Redacted fields + EXPECT_CALL(proto, set_key_code(_)).Times(0); + EXPECT_CALL(proto, set_scan_code(_)).Times(0); + EXPECT_CALL(proto, set_meta_state(_)).Times(0); + + TestProtoConverter::toProtoKeyEvent(event, proto, /*isRedacted=*/true); +} + } // namespace } // namespace android::inputdispatcher::trace |