Mir

Merge lp:~andreas-pokorny/mir/use-monotonic-clock-for-input into lp:mir

Proposed by Andreas Pokorny
Status: Merged
Approved by: Andreas Pokorny
Approved revision: no longer in the source branch.
Merged at revision: 3104
Proposed branch: lp:~andreas-pokorny/mir/use-monotonic-clock-for-input
Merge into: lp:mir
Diff against target: 162 lines (+28/-48)
5 files modified
3rd_party/android-input/android/frameworks/native/libs/utils/Timers.cpp (+4/-30)
src/common/logging/input_timestamp.cpp (+6/-12)
src/platforms/evdev/libinput_ptr.cpp (+13/-1)
src/server/input/key_repeat_dispatcher.cpp (+1/-1)
tests/mir_test_framework/fake_input_device_impl.cpp (+4/-4)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/use-monotonic-clock-for-input
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alan Griffiths Approve
Chris Halse Rogers Approve
Review via email: mp+277635@code.launchpad.net

Commit message

Switch to monotonic clock for everything input related

sytemTime from android-input is used by client and server within the input receiver to calculate an assumed frame time, and to attach timestamps to input events. The evdev platform now ensures with EVIOCSCLOCKID(CLOCK_MONOTONIC) that for every device opened through libinput CLOCK_MONOTONIC is used. Note that EventHub.cpp does the same.
KeyRepeatDispatcher used to emit timer events from system_clock which uses CLOCK_REALTIME. Similar reports and fake event devices required adaptation too.

Before this change CLOCK_REALTIME was used because the default build configuration of android-input refrained from using any other clock (c.f. HAVE_POSIX_CLOCKS). Hence the input event timestamps were replaced by CLOCK_REALTIME timestamps. And everything else had to follow that setup.

Description of the change

As opposed to the previous attempt, this MP does not introduce the idea of a Clock passed to platforms. Instead it relies on the underlying system to come up with good timestamps. Especially for evdev events the timestamps from the device are more accurate than the ones generated when the system compositor gets to interpret the results from libinput.

So in the end this MP just changes the already spread time stamp related bits to use the monotonic clock.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Seems reasonable.

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

+ auto age =
+ std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now().time_since_epoch() - when);

1. A bit wordy.
2. could be const.

    using namespace std::chrono;
    ...
    duration<double, std::milli> const age{steady_clock::now().time_since_epoch() - when};

review: Approve
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) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '3rd_party/android-input/android/frameworks/native/libs/utils/Timers.cpp'
--- 3rd_party/android-input/android/frameworks/native/libs/utils/Timers.cpp 2015-08-18 01:35:15 +0000
+++ 3rd_party/android-input/android/frameworks/native/libs/utils/Timers.cpp 2015-11-18 09:58:11 +0000
@@ -20,38 +20,12 @@
20#include <utils/Timers.h>20#include <utils/Timers.h>
21#include <std/Log.h>21#include <std/Log.h>
2222
23#include <stdlib.h>
24#include <stdio.h>
25#include <unistd.h>
26#include <sys/time.h>
27#include <time.h>
28#include <errno.h>
29#include <limits.h>23#include <limits.h>
3024#include <chrono>
31#ifdef HAVE_WIN32_THREADS25
32#include <windows.h>26std::chrono::nanoseconds systemTime(int /*clock => always MONOTONIC*/)
33#endif
34
35std::chrono::nanoseconds systemTime(int clock)
36{27{
37#if defined(HAVE_POSIX_CLOCKS)28 return {std::chrono::steady_clock::now().time_since_epoch()};
38 static const clockid_t clocks[] = {
39 CLOCK_REALTIME,
40 CLOCK_MONOTONIC,
41 CLOCK_PROCESS_CPUTIME_ID,
42 CLOCK_THREAD_CPUTIME_ID
43 };
44 struct timespec t;
45 t.tv_sec = t.tv_nsec = 0;
46 clock_gettime(clocks[clock], &t);
47 return std::chrono::nanoseconds(t.tv_sec)*1000000000LL + t.tv_nsec;
48#else
49 // we don't support the clocks here.
50 struct timeval t;
51 t.tv_sec = t.tv_usec = 0;
52 gettimeofday(&t, NULL);
53 return std::chrono::nanoseconds(t.tv_sec)*1000000000LL + std::chrono::nanoseconds(t.tv_usec)*1000LL;
54#endif
55}29}
5630
57int toMillisecondTimeoutDelay(std::chrono::nanoseconds referenceTime, std::chrono::nanoseconds timeoutTime)31int toMillisecondTimeoutDelay(std::chrono::nanoseconds referenceTime, std::chrono::nanoseconds timeoutTime)
5832
=== modified file 'src/common/logging/input_timestamp.cpp'
--- src/common/logging/input_timestamp.cpp 2015-06-17 05:20:42 +0000
+++ src/common/logging/input_timestamp.cpp 2015-11-18 09:58:11 +0000
@@ -19,21 +19,15 @@
19#include "mir/logging/input_timestamp.h"19#include "mir/logging/input_timestamp.h"
20#include <cstdio>20#include <cstdio>
2121
22std::string mir::logging::input_timestamp(std::chrono::nanoseconds when)22using namespace std::chrono;
23std::string mir::logging::input_timestamp(nanoseconds when)
23{24{
24 // Input events use CLOCK_REALTIME, and so we must...25 // Input events use CLOCK_MONOTONIC, and so we must...
25 struct timespec ts;26 duration<double, std::milli> const age = steady_clock::now().time_since_epoch() - when;
26 clock_gettime(CLOCK_REALTIME, &ts);
27
28 std::chrono::nanoseconds now = std::chrono::nanoseconds(ts.tv_sec * 1000000000LL + ts.tv_nsec);
29 std::chrono::nanoseconds age = now - when;
3027
31 char str[64];28 char str[64];
32 snprintf(str, sizeof str, "%lld (%ld.%06ld ms ago)",29 snprintf(str, sizeof str, "%lld (%.6fms ago)",
33 static_cast<long long>(when.count()),30 static_cast<long long>(when.count()),age.count());
34 static_cast<long>(age.count() / 1000000LL),
35 static_cast<long>(age.count() % 1000000LL));
3631
37 return std::string(str);32 return std::string(str);
38}33}
39
4034
=== modified file 'src/platforms/evdev/libinput_ptr.cpp'
--- src/platforms/evdev/libinput_ptr.cpp 2015-08-07 16:51:20 +0000
+++ src/platforms/evdev/libinput_ptr.cpp 2015-11-18 09:58:11 +0000
@@ -23,14 +23,26 @@
23#include <sys/stat.h>23#include <sys/stat.h>
24#include <fcntl.h>24#include <fcntl.h>
25#include <unistd.h>25#include <unistd.h>
26#include <linux/input.h>
2627
27namespace mie = mir::input::evdev;28namespace mie = mir::input::evdev;
2829
29namespace30namespace
30{31{
32int use_monotonic_clock(int evdev)
33{
34 if (evdev != -1)
35 {
36 int const clockId = CLOCK_MONOTONIC;
37 // Switch each evdev 'client' to MONOTONIC
38 ioctl(evdev, EVIOCSCLOCKID, &clockId);
39 }
40 return evdev;
41}
42
31int fd_open(const char* path, int flags, void* /*userdata*/)43int fd_open(const char* path, int flags, void* /*userdata*/)
32{44{
33 return ::open(path, flags);45 return use_monotonic_clock(::open(path, flags));
34}46}
3547
36void fd_close(int fd, void* /*userdata*/)48void fd_close(int fd, void* /*userdata*/)
3749
=== modified file 'src/server/input/key_repeat_dispatcher.cpp'
--- src/server/input/key_repeat_dispatcher.cpp 2015-10-08 00:23:43 +0000
+++ src/server/input/key_repeat_dispatcher.cpp 2015-11-18 09:58:11 +0000
@@ -118,7 +118,7 @@
118 {118 {
119 std::lock_guard<std::mutex> lg(repeat_state_mutex);119 std::lock_guard<std::mutex> lg(repeat_state_mutex);
120120
121 ev.key.event_time = std::chrono::high_resolution_clock::now().time_since_epoch();121 ev.key.event_time = std::chrono::steady_clock::now().time_since_epoch();
122 ev.key.mac = cookie_factory->timestamp_to_cookie(ev.key.event_time.count()).mac;122 ev.key.mac = cookie_factory->timestamp_to_cookie(ev.key.event_time.count()).mac;
123 next_dispatcher->dispatch(ev);123 next_dispatcher->dispatch(ev);
124124
125125
=== modified file 'tests/mir_test_framework/fake_input_device_impl.cpp'
--- tests/mir_test_framework/fake_input_device_impl.cpp 2015-11-04 07:43:28 +0000
+++ tests/mir_test_framework/fake_input_device_impl.cpp 2015-11-18 09:58:11 +0000
@@ -97,7 +97,7 @@
97 xkb_keysym_t key_code = 0;97 xkb_keysym_t key_code = 0;
9898
99 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(99 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
100 std::chrono::system_clock::now().time_since_epoch());100 std::chrono::steady_clock::now().time_since_epoch());
101101
102 auto input_action =102 auto input_action =
103 (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down : mir_keyboard_action_up;103 (key_params.action == synthesis::EventAction::Down) ? mir_keyboard_action_down : mir_keyboard_action_up;
@@ -112,7 +112,7 @@
112void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::ButtonParameters const& button)112void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::ButtonParameters const& button)
113{113{
114 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(114 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
115 std::chrono::system_clock::now().time_since_epoch());115 std::chrono::steady_clock::now().time_since_epoch());
116 auto action = update_buttons(button.action, mie::to_pointer_button(button.button, settings.handedness));116 auto action = update_buttons(button.action, mie::to_pointer_button(button.button, settings.handedness));
117 auto button_event = builder->pointer_event(event_time,117 auto button_event = builder->pointer_event(event_time,
118 action,118 action,
@@ -149,7 +149,7 @@
149 BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));149 BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));
150150
151 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(151 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
152 std::chrono::system_clock::now().time_since_epoch());152 std::chrono::steady_clock::now().time_since_epoch());
153 // constant scaling is used here to simplify checking for the153 // constant scaling is used here to simplify checking for the
154 // expected results. Default settings of the device lead to no154 // expected results. Default settings of the device lead to no
155 // scaling at all.155 // scaling at all.
@@ -183,7 +183,7 @@
183 BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));183 BOOST_THROW_EXCEPTION(std::runtime_error("Device is not started."));
184184
185 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(185 auto event_time = std::chrono::duration_cast<std::chrono::nanoseconds>(
186 std::chrono::system_clock::now().time_since_epoch());186 std::chrono::steady_clock::now().time_since_epoch());
187187
188 auto touch_event = builder->touch_event(event_time);188 auto touch_event = builder->touch_event(event_time);
189189

Subscribers

People subscribed via source and target branches