diff options
Diffstat (limited to 'ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc')
-rw-r--r-- | ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc | 268 |
1 files changed, 230 insertions, 38 deletions
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc index fc5d367..e7019b0 100644 --- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc +++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc @@ -9,10 +9,11 @@ #include <utility> #include <vector> +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(__ANDROID__) +#if defined(__ANDROID__) || defined(__ANDROID_HOST__) #include <linux/input-event-codes.h> -#include "chrome_to_android_compatibility_test_support.h" +#include "chrome_to_android_compatibility.h" #else #include "ui/events/ozone/evdev/event_device_test_util.h" #endif @@ -20,9 +21,12 @@ #include "ui/events/ozone/evdev/touch_filter/palm_detection_filter.h" #include "ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h" +using ::testing::ElementsAre; +using ::testing::IsEmpty; + namespace ui { -#if defined(__ANDROID__) +#if defined(__ANDROID__) || defined(__ANDROID_HOST__) /** * The tests that require an actual device (something that responds to ioctls) * have been removed. The rest of the tests were simplified by modifying the @@ -83,7 +87,13 @@ bool CapabilitiesToDeviceInfo(DeviceType, EventDeviceInfo*) { } #endif -class NeuralStylusPalmDetectionFilterUtilTest : public testing::Test { +MATCHER_P(SampleTime, time, "Does the sample have given time.") { + *result_listener << "Sample time" << arg.time << " is not " << time; + return time == arg.time; +} + +class NeuralStylusPalmDetectionFilterUtilTest + : public testing::TestWithParam<bool> { public: NeuralStylusPalmDetectionFilterUtilTest() = default; @@ -101,6 +111,11 @@ class NeuralStylusPalmDetectionFilterUtilTest : public testing::Test { touch_.tracking_id = 22; touch_.x = 21; touch_.y = 20; + model_config_.max_sample_count = 3; + const bool resample_touch = GetParam(); + if (resample_touch) { + model_config_.resample_period = base::Milliseconds(8); + } } protected: @@ -109,8 +124,16 @@ class NeuralStylusPalmDetectionFilterUtilTest : public testing::Test { NeuralStylusPalmDetectionFilterModelConfig model_config_; }; -#if !defined(__ANDROID__) -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, DistilledNocturneTest) { +INSTANTIATE_TEST_SUITE_P(ParametricUtilTest, + NeuralStylusPalmDetectionFilterUtilTest, + ::testing::Bool(), + [](const auto& paramInfo) { + return paramInfo.param ? "ResamplingEnabled" + : "ResamplingDisabled"; + }); + +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, DistilledNocturneTest) { const PalmFilterDeviceInfo nocturne_distilled = CreatePalmFilterDeviceInfo(nocturne_touchscreen_); EXPECT_FLOAT_EQ(nocturne_distilled.max_x, @@ -128,9 +151,9 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, DistilledNocturneTest) { nocturne_touchscreen_.GetAbsResolution(ABS_MT_TOUCH_MINOR)); } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, NoMinorResTest) { - // Nocturne has minor resolution: but lets pretend it didnt. we should recover - // "1" as the resolution. +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, NoMinorResTest) { + // Nocturne has minor resolution, but let's pretend it doesn't. we should + // recover "1" as the resolution. auto abs_info = nocturne_touchscreen_.GetAbsInfoByCode(ABS_MT_TOUCH_MINOR); abs_info.resolution = 0; nocturne_touchscreen_.SetAbsInfo(ABS_MT_TOUCH_MINOR, abs_info); @@ -141,12 +164,12 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, NoMinorResTest) { } #endif -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, DistillerKohakuTest) { +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, DistillerKohakuTest) { EventDeviceInfo kohaku_touchscreen; ASSERT_TRUE( CapabilitiesToDeviceInfo(kKohakuTouchscreen, &kohaku_touchscreen)); const PalmFilterDeviceInfo kohaku_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(kohaku_touchscreen); #else CreatePalmFilterDeviceInfo(kKohakuTouchscreen); @@ -156,11 +179,11 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, DistillerKohakuTest) { EXPECT_EQ(1, kohaku_distilled.y_res); } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, DistilledLinkTest) { +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, DistilledLinkTest) { EventDeviceInfo link_touchscreen; ASSERT_TRUE(CapabilitiesToDeviceInfo(kLinkTouchscreen, &link_touchscreen)); const PalmFilterDeviceInfo link_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(link_touchscreen); #else CreatePalmFilterDeviceInfo(kLinkTouchscreen); @@ -171,10 +194,10 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, DistilledLinkTest) { link_distilled.minor_radius_res); } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterSampleTest) { +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterSampleTest) { base::TimeTicks time = base::TimeTicks() + base::Seconds(30); const PalmFilterDeviceInfo nocturne_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(nocturne_touchscreen_); #else CreatePalmFilterDeviceInfo(kNocturneTouchScreen); @@ -190,12 +213,12 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterSampleTest) { EXPECT_EQ(0.5, sample.edge); } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, LinkTouchscreenSampleTest) { +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, LinkTouchscreenSampleTest) { EventDeviceInfo link_touchscreen; base::TimeTicks time = base::TimeTicks() + base::Seconds(30); ASSERT_TRUE(CapabilitiesToDeviceInfo(kLinkTouchscreen, &link_touchscreen)); const PalmFilterDeviceInfo link_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(link_touchscreen); #else CreatePalmFilterDeviceInfo(kLinkTouchscreen); @@ -210,15 +233,15 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, LinkTouchscreenSampleTest) { EXPECT_FLOAT_EQ(12.5, sample.minor_radius); } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterStrokeTest) { - PalmFilterStroke stroke(3); // maxsize: 3. - EXPECT_EQ(0, stroke.tracking_id()); +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterStrokeTest) { + PalmFilterStroke stroke(model_config_, /*tracking_id*/ 55); + touch_.tracking_id = 55; // With no points, center is 0. EXPECT_EQ(gfx::PointF(0., 0.), stroke.GetCentroid()); base::TimeTicks time = base::TimeTicks() + base::Seconds(30); const PalmFilterDeviceInfo nocturne_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(nocturne_touchscreen_); #else CreatePalmFilterDeviceInfo(kNocturneTouchScreen); @@ -228,7 +251,8 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterStrokeTest) { touch_.x = 15 + i; PalmFilterSample sample = CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled); - stroke.AddSample(std::move(sample)); + time += base::Milliseconds(8); + stroke.ProcessSample(std::move(sample)); EXPECT_EQ(touch_.tracking_id, stroke.tracking_id()); if (i < 3) { if (i == 0) { @@ -248,19 +272,18 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterStrokeTest) { ASSERT_FLOAT_EQ(expected_centroid.x(), stroke.GetCentroid().x()) << "failed at i " << i; } - stroke.SetTrackingId(55); - EXPECT_EQ(55, stroke.tracking_id()); } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterStrokeBiggestSizeTest) { - PalmFilterStroke stroke(3); - PalmFilterStroke no_minor_stroke(3); // maxsize: 3. + PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0); + PalmFilterStroke no_minor_stroke(model_config_, /*tracking_id*/ 0); + touch_.tracking_id = stroke.tracking_id(); EXPECT_EQ(0, stroke.BiggestSize()); base::TimeTicks time = base::TimeTicks() + base::Seconds(30); const PalmFilterDeviceInfo nocturne_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(nocturne_touchscreen_); #else CreatePalmFilterDeviceInfo(kNocturneTouchScreen); @@ -271,24 +294,44 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterSample sample = CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled); EXPECT_EQ(static_cast<uint64_t>(i), stroke.samples_seen()); - stroke.AddSample(sample); + stroke.ProcessSample(sample); EXPECT_FLOAT_EQ((1 + i) * (2 + i), stroke.BiggestSize()); PalmFilterSample second_sample = CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled); second_sample.minor_radius = 0; - no_minor_stroke.AddSample(std::move(second_sample)); + no_minor_stroke.ProcessSample(std::move(second_sample)); EXPECT_FLOAT_EQ((2 + i) * (2 + i), no_minor_stroke.BiggestSize()); - EXPECT_EQ(std::min(3ul, 1ul + i), stroke.samples().size()); + ASSERT_EQ(std::min(3ul, 1ul + i), stroke.samples().size()); + time += base::Milliseconds(8); } } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, StrokeGetMaxMajorTest) { - PalmFilterStroke stroke(3); +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, UnscaledMajorMinorResolution) { + model_config_.radius_polynomial_resize = {}; + PalmFilterDeviceInfo device_info; + device_info.x_res = 2; + device_info.y_res = 5; + device_info.major_radius_res = 2; + device_info.minor_radius_res = 5; + device_info.minor_radius_supported = true; + touch_.major = 20; + touch_.minor = 10; + touch_.orientation = 0; + base::TimeTicks time = base::TimeTicks::UnixEpoch() + base::Seconds(30); + PalmFilterSample sample = + CreatePalmFilterSample(touch_, time, model_config_, device_info); + EXPECT_EQ(20 / 2, sample.major_radius); + EXPECT_EQ(10 / 5, sample.minor_radius); +} + +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, StrokeGetMaxMajorTest) { + PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0); + touch_.tracking_id = stroke.tracking_id(); EXPECT_FLOAT_EQ(0, stroke.MaxMajorRadius()); base::TimeTicks time = base::TimeTicks::UnixEpoch() + base::Seconds(30); const PalmFilterDeviceInfo nocturne_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(nocturne_touchscreen_); #else CreatePalmFilterDeviceInfo(kNocturneTouchScreen); @@ -300,17 +343,17 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, StrokeGetMaxMajorTest) { CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled); time += base::Milliseconds(8); EXPECT_EQ(static_cast<uint64_t>(i - 1), stroke.samples_seen()); - stroke.AddSample(sample); + stroke.ProcessSample(sample); EXPECT_FLOAT_EQ(i, stroke.MaxMajorRadius()); } } -TEST_F(NeuralStylusPalmDetectionFilterUtilTest, SampleRadiusConversion) { +TEST_P(NeuralStylusPalmDetectionFilterUtilTest, SampleRadiusConversion) { // A single number: a _constant_. model_config_.radius_polynomial_resize = {71.3}; base::TimeTicks time = base::TimeTicks::UnixEpoch() + base::Seconds(30); const PalmFilterDeviceInfo nocturne_distilled = -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__) CreatePalmFilterDeviceInfo(nocturne_touchscreen_); #else CreatePalmFilterDeviceInfo(kNocturneTouchScreen); @@ -328,4 +371,153 @@ TEST_F(NeuralStylusPalmDetectionFilterUtilTest, SampleRadiusConversion) { EXPECT_FLOAT_EQ(0.1 * 24 * 24 + 0.4 * 24 - 5.0, sample.minor_radius); } -} // namespace ui
\ No newline at end of file +TEST(PalmFilterStrokeTest, NumberOfResampledValues) { + NeuralStylusPalmDetectionFilterModelConfig model_config_; + model_config_.max_sample_count = 3; + model_config_.resample_period = base::Milliseconds(8); + base::TimeTicks down_time = base::TimeTicks::UnixEpoch() + base::Seconds(30); + + PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0); + const PalmFilterDeviceInfo device_info; + + // Initially, no samples + ASSERT_THAT(stroke.samples(), IsEmpty()); + ASSERT_EQ(0u, stroke.samples_seen()); + + // Add first sample at time = T + InProgressTouchEvdev touch_; + touch_.tracking_id = stroke.tracking_id(); + PalmFilterSample sample = + CreatePalmFilterSample(touch_, down_time, model_config_, device_info); + stroke.ProcessSample(sample); + ASSERT_THAT(stroke.samples(), ElementsAre(SampleTime(down_time))); + ASSERT_EQ(1u, stroke.samples_seen()); + + // Add second sample at time = T + 4ms. All samples are stored, even if it's + // before the next resample time. + base::TimeTicks time = down_time + base::Milliseconds(4); + sample = CreatePalmFilterSample(touch_, time, model_config_, device_info); + stroke.ProcessSample(sample); + ASSERT_THAT(stroke.samples(), + ElementsAre(SampleTime(down_time), SampleTime(time))); + ASSERT_EQ(2u, stroke.samples_seen()); + + // Add third sample at time = T + 10ms. + time = down_time + base::Milliseconds(10); + sample = CreatePalmFilterSample(touch_, time, model_config_, device_info); + stroke.ProcessSample(sample); + ASSERT_THAT(stroke.samples(), + ElementsAre(SampleTime(down_time), + SampleTime(down_time + base::Milliseconds(4)), + SampleTime(down_time + base::Milliseconds(10)))); + ASSERT_EQ(3u, stroke.samples_seen()); +} + +TEST(PalmFilterStrokeTest, ResamplingTest) { + NeuralStylusPalmDetectionFilterModelConfig model_config_; + model_config_.max_sample_count = 3; + model_config_.resample_period = base::Milliseconds(8); + + PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0); + PalmFilterDeviceInfo device_info; + device_info.minor_radius_supported = true; + + // Add first sample at time = T + InProgressTouchEvdev touch_; + touch_.tracking_id = stroke.tracking_id(); + touch_.x = 1; + touch_.y = 2; + touch_.major = 4; + touch_.minor = 3; + base::TimeTicks down_time = base::TimeTicks::UnixEpoch() + base::Seconds(30); + PalmFilterSample sample1 = + CreatePalmFilterSample(touch_, down_time, model_config_, device_info); + stroke.ProcessSample(sample1); + // First sample should not be modified + ASSERT_THAT(stroke.samples(), ElementsAre(sample1)); + + // Add second sample at time = T + 2ms. It's not yet time for the new frame, + // so no new sample should be generated. + base::TimeTicks time = down_time + base::Milliseconds(4); + touch_.x = 100; + touch_.y = 20; + touch_.major = 12; + touch_.minor = 11; + PalmFilterSample sample2 = + CreatePalmFilterSample(touch_, time, model_config_, device_info); + stroke.ProcessSample(sample2); + // The samples should remain unchanged + ASSERT_THAT(stroke.samples(), ElementsAre(sample1, sample2)); + + // Add third sample at time = T + 12ms. A resampled event at time = T + 8ms + // should be generated. + time = down_time + base::Milliseconds(12); + touch_.x = 200; + touch_.y = 24; + touch_.major = 14; + touch_.minor = 13; + PalmFilterSample sample3 = + CreatePalmFilterSample(touch_, time, model_config_, device_info); + stroke.ProcessSample(sample3); + ASSERT_THAT(stroke.samples(), ElementsAre(sample1, sample2, sample3)); +} + +/** + * There should always be at least (max_sample_count - 1) * resample_period + * worth of samples. However, that's not sufficient. In the cases where the gap + * between samples is very large (larger than the sample horizon), there needs + * to be another sample in order to calculate resampled values throughout the + * entire range. + */ +TEST(PalmFilterStrokeTest, MultipleResampledValues) { + NeuralStylusPalmDetectionFilterModelConfig model_config_; + model_config_.max_sample_count = 3; + model_config_.resample_period = base::Milliseconds(8); + + PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0); + PalmFilterDeviceInfo device_info; + device_info.minor_radius_supported = true; + + // Add first sample at time = T + InProgressTouchEvdev touch_; + touch_.tracking_id = stroke.tracking_id(); + touch_.x = 0; + touch_.y = 10; + touch_.major = 200; + touch_.minor = 100; + base::TimeTicks down_time = base::TimeTicks::UnixEpoch() + base::Seconds(30); + PalmFilterSample sample1 = + CreatePalmFilterSample(touch_, down_time, model_config_, device_info); + stroke.ProcessSample(sample1); + // First sample should go in as is + ASSERT_THAT(stroke.samples(), ElementsAre(sample1)); + + // Add second sample at time = T + 20ms. + base::TimeTicks time = down_time + base::Milliseconds(20); + touch_.x = 20; + touch_.y = 30; + touch_.major = 220; + touch_.minor = 120; + PalmFilterSample sample2 = + CreatePalmFilterSample(touch_, time, model_config_, device_info); + stroke.ProcessSample(sample2); + + ASSERT_THAT(stroke.samples(), ElementsAre(sample1, sample2)); + + // Verify resampled sample : time = T + 8ms + PalmFilterSample resampled_sample = + stroke.GetSampleAt(down_time + base::Milliseconds(8)); + EXPECT_EQ(8, resampled_sample.point.x()); + EXPECT_EQ(18, resampled_sample.point.y()); + EXPECT_EQ(220, resampled_sample.major_radius); + EXPECT_EQ(120, resampled_sample.minor_radius); + + // Verify resampled sample : time = T + 16ms + resampled_sample = stroke.GetSampleAt(down_time + base::Milliseconds(16)); + EXPECT_EQ(16, resampled_sample.point.x()); + EXPECT_EQ(26, resampled_sample.point.y()); + EXPECT_EQ(220, resampled_sample.major_radius); + EXPECT_EQ(120, resampled_sample.minor_radius); +} + +} // namespace ui |