Mir

Merge lp:~vanvugt/mir/fix-1372300 into lp:mir

Proposed by Daniel van Vugt
Status: Merged
Merged at revision: 1936
Proposed branch: lp:~vanvugt/mir/fix-1372300
Merge into: lp:mir
Diff against target: 84 lines (+46/-13)
2 files modified
src/common/input/android/android_input_receiver.cpp (+1/-13)
tests/unit-tests/client/input/test_android_input_receiver.cpp (+45/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/fix-1372300
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Alexandros Frantzis (community) Approve
Review via email: mp+235573@code.launchpad.net

Commit message

Fix jerky/stuttering event delivery that could happen inside
nested servers sometimes (LP: #1372300)

Waiting significantly longer than a frame before consuming previously
batched events is too dangerous in slow raw-event environments
(nested servers or very slow input devices). It causes frame skipping.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

If you decide to do any manual testing, beware of bug 1372850, which is technically unrelated.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Confirming this fixes the issue.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/common/input/android/android_input_receiver.cpp'
2--- src/common/input/android/android_input_receiver.cpp 2014-09-11 05:51:44 +0000
3+++ src/common/input/android/android_input_receiver.cpp 2014-09-24 07:21:12 +0000
4@@ -134,23 +134,11 @@
5 }
6
7 auto reduced_timeout = timeout;
8- if (input_consumer->hasDeferredEvent())
9+ if (input_consumer->hasDeferredEvent() || input_consumer->hasPendingBatch())
10 {
11 // consume() didn't finish last time. Retry it immediately.
12 reduced_timeout = std::chrono::milliseconds::zero();
13 }
14- else if (input_consumer->hasPendingBatch())
15- {
16- /*
17- * A batch is pending and must be completed or else the client could
18- * be starved of events. But don't hurry. A continuous motion gesture
19- * will wake us up much sooner than 50ms. This timeout is only reached
20- * in the case that motion has ended (fingers lifted).
21- */
22- std::chrono::milliseconds const motion_idle_timeout(50);
23- if (timeout.count() < 0 || timeout > motion_idle_timeout)
24- reduced_timeout = motion_idle_timeout;
25- }
26
27 auto result = looper->pollOnce(reduced_timeout.count());
28 if (result == ALOOPER_POLL_WAKE)
29
30=== modified file 'tests/unit-tests/client/input/test_android_input_receiver.cpp'
31--- tests/unit-tests/client/input/test_android_input_receiver.cpp 2014-09-11 05:51:44 +0000
32+++ tests/unit-tests/client/input/test_android_input_receiver.cpp 2014-09-24 07:21:12 +0000
33@@ -204,6 +204,51 @@
34 EXPECT_FALSE(receiver.next_event(std::chrono::milliseconds(1), ev)); // Minimal timeout needed for valgrind
35 }
36
37+TEST_F(AndroidInputReceiverSetup, slow_raw_input_doesnt_cause_frameskipping)
38+{ // Regression test for LP: #1372300
39+ using namespace testing;
40+ using namespace std::chrono;
41+
42+ nsecs_t t = 0;
43+
44+ mircva::InputReceiver receiver(
45+ client_fd, std::make_shared<mircv::NullInputReceiverReport>(),
46+ [&t](int) { return t; }
47+ );
48+ TestingInputProducer producer(server_fd);
49+
50+ nsecs_t const one_millisecond = 1000000ULL;
51+ nsecs_t const one_second = 1000 * one_millisecond;
52+ nsecs_t const one_frame = one_second / 60;
53+
54+ MirEvent ev;
55+
56+ producer.produce_a_motion_event(123, 456, t);
57+ producer.produce_a_key_event();
58+ flush_channels();
59+
60+ std::chrono::milliseconds const max_timeout(1000);
61+
62+ // Key events don't get resampled. Will be reported first.
63+ ASSERT_TRUE(receiver.next_event(max_timeout, ev));
64+ ASSERT_EQ(mir_event_type_key, ev.type);
65+
66+ // The motion is still too new. Won't be reported yet, but is batched.
67+ auto start = high_resolution_clock::now();
68+ ASSERT_FALSE(receiver.next_event(max_timeout, ev));
69+ auto end = high_resolution_clock::now();
70+ auto duration = end - start;
71+
72+ // Verify we timed out in under a frame (LP: #1372300)
73+ // Sadly using real time as droidinput::Looper doesn't use a mocked clock.
74+ ASSERT_LT(duration_cast<nanoseconds>(duration).count(), one_frame);
75+
76+ // But later in a frame or so, the motion will be reported:
77+ t += one_frame;
78+ ASSERT_TRUE(receiver.next_event(max_timeout, ev));
79+ ASSERT_EQ(mir_event_type_motion, ev.type);
80+}
81+
82 TEST_F(AndroidInputReceiverSetup, rendering_does_not_lag_behind_input)
83 {
84 using namespace testing;

Subscribers

People subscribed via source and target branches