Mir

Merge lp:~andreas-pokorny/mir/dispatchable-event-hub into lp:mir

Proposed by Andreas Pokorny
Status: Merged
Approved by: Andreas Pokorny
Approved revision: no longer in the source branch.
Merged at revision: 2521
Proposed branch: lp:~andreas-pokorny/mir/dispatchable-event-hub
Merge into: lp:mir
Prerequisite: lp:~andreas-pokorny/mir/use-timerfd-in-eventhub
Diff against target: 1162 lines (+409/-351)
22 files modified
3rd_party/android-input/android/frameworks/base/services/input/EventHub.cpp (+2/-2)
3rd_party/android-input/android/frameworks/base/services/input/EventHub.h (+2/-2)
src/include/server/mir/default_server_configuration.h (+1/-5)
src/include/server/mir/server_configuration.h (+0/-1)
src/server/display_server.cpp (+0/-12)
src/server/input/android/CMakeLists.txt (+1/-1)
src/server/input/android/android_input_manager.cpp (+0/-55)
src/server/input/android/android_input_manager.h (+0/-66)
src/server/input/android/input_reader_dispatchable.cpp (+54/-0)
src/server/input/android/input_reader_dispatchable.h (+56/-0)
src/server/input/default_configuration.cpp (+24/-59)
src/server/input/default_input_manager.cpp (+23/-10)
src/server/input/default_input_manager.h (+15/-1)
src/server/run_mir.cpp (+3/-1)
src/server/symbols.map (+0/-2)
tests/include/mir_test_doubles/mock_event_hub.h (+69/-0)
tests/include/mir_test_doubles/mock_input_reader.h (+58/-0)
tests/unit-tests/android_input/test_eventhub.cpp (+6/-6)
tests/unit-tests/input/android/CMakeLists.txt (+2/-1)
tests/unit-tests/input/android/test_android_input_channel_factory.cpp (+3/-126)
tests/unit-tests/input/android/test_input_reader_dispatchable.cpp (+51/-0)
tests/unit-tests/input/test_default_input_manager.cpp (+39/-1)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/dispatchable-event-hub
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Kevin DuBois (community) Approve
Alan Griffiths Approve
Chris Halse Rogers Approve
Alexandros Frantzis (community) Approve
Robert Carr (community) Approve
Daniel van Vugt Pending
Review via email: mp+256445@code.launchpad.net

This proposal supersedes a proposal from 2015-04-15.

Commit message

Remove mir::input::android::InputManager and move InputReader/EventHub control to DefaultInputManager.

Since DefaultInputManager uses a MultiplexingDispatchable, InputReader/EventHub is wrapped by a Dispatchable implementation. This requires EventHub::getEvents to be non blocking.

Description of the change

Preparation Step to turn EventHub into a piece of the evdev input platform.

This change removes the old input reading thread and moves EventHub and InputReader to the Dispatchable driven input reading thread which was up to now only used for the stub-input platform. This requires EventHub::getEvents to not block on the epoll fd. Additionally an initial call to loopOnce is required to let EventHub do the first scan for devices - as the udev monitor is still part of EventHub.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

Overall lgtm

I guess needs info on:

80 SimpleDispatchThread(std::shared_ptr<Dispatchable> const& dispatchee);
81 + SimpleDispatchThread(std::shared_ptr<Dispatchable> const& dispatchee,
82 + std::function<void(std::function<void()> const&)> const& execute_around);

The function of a function seems too tricky... Could we use an enum? eg
SimpleDispatchThread thread(dispatchable, Signals::blocked)
or maybe two different objects? (SimpleDispatchThread wouldn't block, SignalBlockingDispatchThread would block the signals, for instance)

511 + std::shared_ptr<droidinput::EventHubInterface> const event_hub;
512 + std::shared_ptr<droidinput::InputReaderInterface> const reader;
why not private?

review: Needs Information
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote : Posted in a previous version of this proposal

> Overall lgtm
>
> I guess needs info on:
>
> 80 SimpleDispatchThread(std::shared_ptr<Dispatchable> const& dispatchee);
> 81 + SimpleDispatchThread(std::shared_ptr<Dispatchable> const&
> dispatchee,
> 82 + std::function<void(std::function<void()> const&)> const&
> execute_around);
>
> The function of a function seems too tricky... Could we use an enum? eg
> SimpleDispatchThread thread(dispatchable, Signals::blocked)
> or maybe two different objects? (SimpleDispatchThread wouldn't block,
> SignalBlockingDispatchThread would block the signals, for instance)

Yes I am not very fond of it either, but added it because I needed try{ .. } catch .. mir::termiates_with_current_exception. mir::terminate_with_current_exception is part of mirserver, and SimpleDispatchThread is used in the client too..

> 511 + std::shared_ptr<droidinput::EventHubInterface> const event_hub;
> 512 + std::shared_ptr<droidinput::InputReaderInterface> const reader;
> why not private?

ok

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

The thought occurs that another option would be
SimpleDispatchThread(..., std::function<void(std::exception_ptr)> exception_handler).

That would be simpler, as long as we don't need signals in the dispatch thread.

Why do we need signals to be delivered to the dispatch thread? :)

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote : Posted in a previous version of this proposal

> The thought occurs that another option would be
> SimpleDispatchThread(..., std::function<void(std::exception_ptr)>
> exception_handler).
>
> That would be simpler, as long as we don't need signals in the dispatch
> thread.
>
> Why do we need signals to be delivered to the dispatch thread? :)

The signal blocking inside the dispatch thread blocked "raise(SIGTERM)" inside run_mir.cpp. With the last change I solved that by using kill(getpid(), SIGTERM) - which is probably closer to what we want?

Now what should the default implementation of the exception handler do?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

Looks good.

review: Approve
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

LGTM. Addition of wakes() in FakeEventHub suggests a member function would be useful but FakeEventHub is already rather messy *shrug*

review: Approve
Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

LGTM now.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Trivial resolution required:

Text conflict in src/server/display_server.cpp
Text conflict in tests/unit-tests/dispatch/test_simple_dispatch_thread.cpp

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

A very mild nitpicking "Needs Fixing":

94-

That whitespace is useful

~~~~

999 std::lock_guard<std::mutex> lg(guard);
1000 events_available.push_back(event);
1001+ wake();

Partly pre-existing, but I see that code (and change) repeated too many times - how about factoring it out into a function?

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Thanks

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Fix reverted due to bug 1444061. Please fix and resubmit.

review: Needs Resubmitting
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote : Posted in a previous version of this proposal

splitting this up..

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

Nice. +1

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

Looks good.

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)
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
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Still looks good to me.

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

LGTM

review: Approve
Revision history for this message
Kevin DuBois (kdub) wrote :

lgtm too

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
1=== modified file '3rd_party/android-input/android/frameworks/base/services/input/EventHub.cpp'
2--- 3rd_party/android-input/android/frameworks/base/services/input/EventHub.cpp 2015-04-16 08:48:48 +0000
3+++ 3rd_party/android-input/android/frameworks/base/services/input/EventHub.cpp 2015-04-28 11:14:24 +0000
4@@ -889,8 +889,8 @@
5 mLock.unlock(); // release lock before poll, must be before release_wake_lock
6 release_wake_lock(WAKE_LOCK_ID);
7
8- // blocking wait timeout is handled through timer fd
9- int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, -1);
10+ // non blocking call to epoll_wait - blocking happens in dispatch threads
11+ int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, 0);
12
13 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
14 mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock
15
16=== modified file '3rd_party/android-input/android/frameworks/base/services/input/EventHub.h'
17--- 3rd_party/android-input/android/frameworks/base/services/input/EventHub.h 2015-04-16 08:09:52 +0000
18+++ 3rd_party/android-input/android/frameworks/base/services/input/EventHub.h 2015-04-28 11:14:24 +0000
19@@ -196,13 +196,13 @@
20 virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
21
22 /*
23- * Wait for events to become available and returns them.
24+ * Tests for available events and returns them.
25 * After returning, the EventHub holds onto a wake lock until the next call to getEvent.
26 * This ensures that the device will not go to sleep while the event is being processed.
27 * If the device needs to remain awake longer than that, then the caller is responsible
28 * for taking care of it (say, by poking the power manager user activity timer).
29 *
30- * Returns the number of events obtained, or 0 if the timeout expired.
31+ * Returns the number of events obtained.
32 */
33 virtual size_t getEvents(RawEvent* buffer, size_t bufferSize) = 0;
34
35
36=== modified file 'src/include/server/mir/default_server_configuration.h'
37--- src/include/server/mir/default_server_configuration.h 2015-04-14 17:06:33 +0000
38+++ src/include/server/mir/default_server_configuration.h 2015-04-28 11:14:24 +0000
39@@ -314,11 +314,9 @@
40 virtual std::shared_ptr<droidinput::InputReaderInterface> the_input_reader();
41 virtual std::shared_ptr<droidinput::InputReaderPolicyInterface> the_input_reader_policy();
42 virtual std::shared_ptr<droidinput::InputListenerInterface> the_input_translator();
43- virtual std::shared_ptr<input::android::InputThread> the_input_reader_thread();
44
45 // new input reading related parts:
46 virtual std::shared_ptr<input::Platform> the_input_platform();
47- virtual std::shared_ptr<input::InputManager> the_new_input_manager() override;
48 virtual std::shared_ptr<dispatch::MultiplexingDispatchable> the_input_reading_multiplexer();
49 virtual std::shared_ptr<input::InputDeviceRegistry> the_input_device_registry();
50 virtual std::shared_ptr<input::InputDeviceHub> the_input_device_hub();
51@@ -367,7 +365,6 @@
52
53 CachedPtr<input::android::InputRegistrar> input_registrar;
54 CachedPtr<input::android::InputThread> dispatcher_thread;
55- CachedPtr<input::android::InputThread> input_reader_thread;
56 CachedPtr<droidinput::InputDispatcherInterface> android_input_dispatcher;
57 CachedPtr<droidinput::InputEnumerator> input_target_enumerator;
58 CachedPtr<droidinput::InputDispatcherPolicyInterface> android_dispatcher_policy;
59@@ -382,10 +379,9 @@
60 CachedPtr<input::InputReport> input_report;
61 CachedPtr<input::CompositeEventFilter> composite_event_filter;
62 CachedPtr<input::InputManager> input_manager;
63- CachedPtr<input::InputManager> new_input_manager; // currently not used by default
64 CachedPtr<input::DefaultInputDeviceHub> default_input_device_hub; // currently not used by default
65 CachedPtr<input::Platform> input_platform; // currently not used by default
66- CachedPtr<dispatch::MultiplexingDispatchable> input_reading_multiplexer; // currently not used by default
67+ CachedPtr<dispatch::MultiplexingDispatchable> input_reading_multiplexer;
68 CachedPtr<input::InputDispatcher> input_dispatcher;
69 CachedPtr<input::InputSender> input_sender;
70 CachedPtr<input::InputSendObserver> input_send_observer;
71
72=== modified file 'src/include/server/mir/server_configuration.h'
73--- src/include/server/mir/server_configuration.h 2015-04-14 17:06:33 +0000
74+++ src/include/server/mir/server_configuration.h 2015-04-28 11:14:24 +0000
75@@ -64,7 +64,6 @@
76 virtual std::shared_ptr<graphics::Display> the_display() = 0;
77 virtual std::shared_ptr<compositor::Compositor> the_compositor() = 0;
78 virtual std::shared_ptr<input::InputManager> the_input_manager() = 0;
79- virtual std::shared_ptr<input::InputManager> the_new_input_manager() = 0;
80 virtual std::shared_ptr<input::InputDispatcher> the_input_dispatcher() = 0;
81 virtual std::shared_ptr<MainLoop> the_main_loop() = 0;
82 virtual std::shared_ptr<ServerStatusListener> the_server_status_listener() = 0;
83
84=== modified file 'src/server/display_server.cpp'
85--- src/server/display_server.cpp 2015-04-16 20:19:13 +0000
86+++ src/server/display_server.cpp 2015-04-28 11:14:24 +0000
87@@ -80,7 +80,6 @@
88 connector{config.the_connector()},
89 prompt_connector{config.the_prompt_connector()},
90 input_manager{config.the_input_manager()},
91- new_input_manager{config.the_new_input_manager()},
92 main_loop{config.the_main_loop()},
93 server_status_listener{config.the_server_status_listener()},
94 display_changer{config.the_display_changer()}
95@@ -107,10 +106,6 @@
96 [this] { input_manager->stop(); },
97 [this] { input_manager->start(); }};
98
99- TryButRevertIfUnwinding new_input{
100- [this] { new_input_manager->stop(); },
101- [this] { new_input_manager->start(); }};
102-
103 TryButRevertIfUnwinding display_config_processing{
104 [this] { display_changer->pause_display_config_processing(); },
105 [this] { display_changer->resume_display_config_processing(); }};
106@@ -163,10 +158,6 @@
107 [this] { display_changer->resume_display_config_processing(); },
108 [this] { display_changer->pause_display_config_processing(); }};
109
110- TryButRevertIfUnwinding new_input{
111- [this] { new_input_manager->start(); },
112- [this] { new_input_manager->stop(); }};
113-
114 TryButRevertIfUnwinding input{
115 [this] { input_manager->start(); },
116 [this] { input_manager->stop(); }};
117@@ -200,7 +191,6 @@
118 std::shared_ptr<mf::Connector> const connector;
119 std::shared_ptr<mf::Connector> const prompt_connector;
120 std::shared_ptr<mi::InputManager> const input_manager;
121- std::shared_ptr<mi::InputManager> const new_input_manager;
122 std::shared_ptr<mir::MainLoop> const main_loop;
123 std::shared_ptr<mir::ServerStatusListener> const server_status_listener;
124 std::shared_ptr<mir::DisplayChanger> const display_changer;
125@@ -225,7 +215,6 @@
126 p->compositor->start();
127 p->connector->start();
128 p->prompt_connector->start();
129- p->new_input_manager->start();
130 p->input_manager->start();
131 p->input_dispatcher->start();
132
133@@ -235,7 +224,6 @@
134
135 p->input_dispatcher->stop();
136 p->input_manager->stop();
137- p->new_input_manager->stop();
138 p->prompt_connector->stop();
139 p->connector->stop();
140 p->compositor->stop();
141
142=== modified file 'src/server/input/android/CMakeLists.txt'
143--- src/server/input/android/CMakeLists.txt 2015-04-14 17:06:33 +0000
144+++ src/server/input/android/CMakeLists.txt 2015-04-28 11:14:24 +0000
145@@ -1,6 +1,5 @@
146 list(
147 APPEND INPUT_SOURCES
148- ${CMAKE_CURRENT_SOURCE_DIR}/android_input_manager.cpp
149 ${CMAKE_CURRENT_SOURCE_DIR}/android_input_reader_policy.cpp
150 ${CMAKE_CURRENT_SOURCE_DIR}/android_pointer_controller.cpp
151 ${CMAKE_CURRENT_SOURCE_DIR}/android_input_channel.cpp
152@@ -14,6 +13,7 @@
153 ${CMAKE_CURRENT_SOURCE_DIR}/android_input_dispatcher.cpp
154 ${CMAKE_CURRENT_SOURCE_DIR}/common_input_thread.cpp
155 ${CMAKE_CURRENT_SOURCE_DIR}/input_channel_factory.cpp
156+ ${CMAKE_CURRENT_SOURCE_DIR}/input_reader_dispatchable.cpp
157 ${CMAKE_CURRENT_SOURCE_DIR}/input_translator.cpp
158 ${CMAKE_CURRENT_SOURCE_DIR}/input_sender.cpp
159 )
160
161=== removed file 'src/server/input/android/android_input_manager.cpp'
162--- src/server/input/android/android_input_manager.cpp 2015-04-14 18:29:42 +0000
163+++ src/server/input/android/android_input_manager.cpp 1970-01-01 00:00:00 +0000
164@@ -1,55 +0,0 @@
165-/*
166- * Copyright © 2012 Canonical Ltd.
167- *
168- * This program is free software: you can redistribute it and/or modify it
169- * under the terms of the GNU General Public License version 3,
170- * as published by the Free Software Foundation.
171- *
172- * This program is distributed in the hope that it will be useful,
173- * but WITHOUT ANY WARRANTY; without even the implied warranty of
174- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175- * GNU General Public License for more details.
176- *
177- * You should have received a copy of the GNU General Public License
178- * along with this program. If not, see <http://www.gnu.org/licenses/>.
179- *
180- * Authored by: Robert Carr <robert.carr@canonical.com>
181- * Daniel d'Andradra <daniel.dandrada@canonical.com>
182- */
183-
184-#include "mir/input/input_dispatcher.h"
185-#include "android_input_manager.h"
186-#include "android_input_constants.h"
187-#include "android_input_thread.h"
188-#include "android_input_channel.h"
189-
190-#include <EventHub.h>
191-
192-namespace mi = mir::input;
193-namespace mia = mi::android;
194-
195-mia::InputManager::InputManager(std::shared_ptr<droidinput::EventHubInterface> const& event_hub,
196- std::shared_ptr<InputThread> const& reader_thread)
197- : event_hub(event_hub), reader_thread(reader_thread)
198-{
199-}
200-
201-mia::InputManager::~InputManager()
202-{
203- // It is safe to call stop(), even if we haven't been started at all,
204- // or we have been previously started and stopped manually.
205- stop();
206-}
207-
208-void mia::InputManager::stop()
209-{
210- reader_thread->request_stop();
211- event_hub->wake();
212- reader_thread->join();
213-}
214-
215-void mia::InputManager::start()
216-{
217- event_hub->flush();
218- reader_thread->start();
219-}
220
221=== removed file 'src/server/input/android/android_input_manager.h'
222--- src/server/input/android/android_input_manager.h 2015-04-14 18:29:42 +0000
223+++ src/server/input/android/android_input_manager.h 1970-01-01 00:00:00 +0000
224@@ -1,66 +0,0 @@
225-/*
226- * Copyright © 2012 Canonical Ltd.
227- *
228- * This program is free software: you can redistribute it and/or modify it
229- * under the terms of the GNU General Public License version 3,
230- * as published by the Free Software Foundation.
231- *
232- * This program is distributed in the hope that it will be useful,
233- * but WITHOUT ANY WARRANTY; without even the implied warranty of
234- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
235- * GNU General Public License for more details.
236- *
237- * You should have received a copy of the GNU General Public License
238- * along with this program. If not, see <http://www.gnu.org/licenses/>.
239- *
240- * Authored by: Robert Carr <robert.carr@canonical.com>
241- * Daniel d'Andradra <daniel.dandrada@canonical.com>
242- */
243-
244-#ifndef MIR_INPUT_ANDROID_INPUT_MANAGER_H_
245-#define MIR_INPUT_ANDROID_INPUT_MANAGER_H_
246-
247-#include "mir/input/input_manager.h"
248-
249-#include <memory>
250-
251-namespace android
252-{
253-class EventHubInterface;
254-}
255-
256-namespace droidinput = android;
257-
258-namespace mir
259-{
260-
261-namespace input
262-{
263-class InputDispatcher;
264-namespace android
265-{
266-class InputThread;
267-
268-/// Encapsulates the instances of the Android input stack that might require startup and
269-// shutdown calls, that is to say an EventHub tied to an InputReader tied to an
270-// InputDispatcher.
271-class InputManager : public input::InputManager
272-{
273-public:
274- explicit InputManager(std::shared_ptr<droidinput::EventHubInterface> const& event_hub,
275- std::shared_ptr<InputThread> const& reader_thread);
276- virtual ~InputManager();
277-
278- void add_platform(std::shared_ptr<Platform> const&){};
279- void start();
280- void stop();
281-
282-private:
283- std::shared_ptr<droidinput::EventHubInterface> const event_hub;
284- std::shared_ptr<InputThread> const reader_thread;
285-};
286-}
287-}
288-}
289-
290-#endif // MIR_INPUT_INPUT_MANAGER
291
292=== added file 'src/server/input/android/input_reader_dispatchable.cpp'
293--- src/server/input/android/input_reader_dispatchable.cpp 1970-01-01 00:00:00 +0000
294+++ src/server/input/android/input_reader_dispatchable.cpp 2015-04-28 11:14:24 +0000
295@@ -0,0 +1,54 @@
296+/*
297+ * Copyright © 2015 Canonical Ltd.
298+ *
299+ * This program is free software: you can redistribute it and/or modify
300+ * it under the terms of the GNU General Public License version 3 as
301+ * published by the Free Software Foundation.
302+ *
303+ * This program is distributed in the hope that it will be useful,
304+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
305+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
306+ * GNU General Public License for more details.
307+ *
308+ * You should have received a copy of the GNU General Public License
309+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
310+ *
311+ * Authored by: Andreas Pokorny <andreas.pokorny@gmail.com>
312+ */
313+
314+#include "input_reader_dispatchable.h"
315+#include <EventHub.h>
316+#include <InputReader.h>
317+
318+namespace md = mir::dispatch;
319+namespace mia = mir::input::android;
320+
321+mia::InputReaderDispatchable::InputReaderDispatchable(
322+ std::shared_ptr<droidinput::EventHubInterface> const& event_hub,
323+ std::shared_ptr<droidinput::InputReaderInterface> const& reader)
324+ : event_hub(event_hub), reader(reader)
325+{}
326+
327+mir::Fd mia::InputReaderDispatchable::watch_fd() const
328+{
329+ return event_hub->fd();
330+}
331+
332+bool mia::InputReaderDispatchable::dispatch(md::FdEvents events)
333+{
334+ if (events & md::FdEvent::error)
335+ return false;
336+ if (events & md::FdEvent::readable)
337+ reader->loopOnce();
338+ return true;
339+}
340+
341+md::FdEvents mia::InputReaderDispatchable::relevant_events() const
342+{
343+ return md::FdEvent::readable;
344+}
345+
346+void mia::InputReaderDispatchable::start()
347+{
348+ event_hub->flush();
349+}
350
351=== added file 'src/server/input/android/input_reader_dispatchable.h'
352--- src/server/input/android/input_reader_dispatchable.h 1970-01-01 00:00:00 +0000
353+++ src/server/input/android/input_reader_dispatchable.h 2015-04-28 11:14:24 +0000
354@@ -0,0 +1,56 @@
355+/*
356+ * Copyright © 2015 Canonical Ltd.
357+ *
358+ * This program is free software: you can redistribute it and/or modify
359+ * it under the terms of the GNU General Public License version 3 as
360+ * published by the Free Software Foundation.
361+ *
362+ * This program is distributed in the hope that it will be useful,
363+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
364+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
365+ * GNU General Public License for more details.
366+ *
367+ * You should have received a copy of the GNU General Public License
368+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
369+ *
370+ * Authored by: Andreas Pokorny <andreas.pokorny@gmail.com>
371+ */
372+
373+#ifndef MIR_INPUT_ANDROID_INPUT_READER_DISPATCHABLE_H_
374+#define MIR_INPUT_ANDROID_INPUT_READER_DISPATCHABLE_H_
375+
376+#include "mir/dispatch/dispatchable.h"
377+
378+namespace android
379+{
380+class EventHubInterface;
381+class InputReaderInterface;
382+}
383+namespace droidinput = android;
384+
385+namespace mir
386+{
387+namespace input
388+{
389+namespace android
390+{
391+
392+struct InputReaderDispatchable : mir::dispatch::Dispatchable
393+{
394+ InputReaderDispatchable(std::shared_ptr<droidinput::EventHubInterface> const& event_hub,
395+ std::shared_ptr<droidinput::InputReaderInterface> const& reader);
396+ Fd watch_fd() const override;
397+ bool dispatch(mir::dispatch::FdEvents events) override;
398+ mir::dispatch::FdEvents relevant_events() const override;
399+ void start();
400+
401+private:
402+ std::shared_ptr<droidinput::EventHubInterface> const event_hub;
403+ std::shared_ptr<droidinput::InputReaderInterface> const reader;
404+};
405+
406+}
407+}
408+}
409+
410+#endif
411
412=== modified file 'src/server/input/default_configuration.cpp'
413--- src/server/input/default_configuration.cpp 2015-04-23 20:17:52 +0000
414+++ src/server/input/default_configuration.cpp 2015-04-28 11:14:24 +0000
415@@ -29,7 +29,6 @@
416 #include "android/event_filter_dispatcher_policy.h"
417 #include "android/input_sender.h"
418 #include "android/input_channel_factory.h"
419-#include "android/android_input_manager.h"
420 #include "android/input_translator.h"
421 #include "display_input_region.h"
422 #include "event_filter_chain.h"
423@@ -217,48 +216,6 @@
424 });
425 }
426
427-std::shared_ptr<mi::InputManager>
428-mir::DefaultServerConfiguration::the_input_manager()
429-{
430- // As the input configuration is structured now, if there is no
431- // InputReader (as in the nested case) there will be nothing to instate
432- // and keep alive the cursor and its controller.
433- // We use the CursorControllingInputManager for this purpose.
434- struct CursorControllingInputManager : public mi::NullInputManager
435- {
436- CursorControllingInputManager(
437- std::shared_ptr<mi::CursorListener> const& cursor_listener)
438- : cursor_listener(cursor_listener)
439- {
440- }
441-
442- std::shared_ptr<mi::CursorListener> const cursor_listener;
443- };
444-
445- return input_manager(
446- [&, this]() -> std::shared_ptr<mi::InputManager>
447- {
448- auto const options = the_options();
449- bool input_reading_required =
450- options->get<bool>(options::enable_input_opt) &&
451- !options->is_set(options::host_socket_opt);
452-
453- if (input_reading_required)
454- {
455- if (options->get<std::string>(options::legacy_input_report_opt) == options::log_opt_value)
456- mr::legacy_input::initialize(the_logger());
457-
458- return std::make_shared<mia::InputManager>(
459- the_event_hub(),
460- the_input_reader_thread());
461- }
462- else if (options->get<bool>(options::enable_input_opt))
463- return std::make_shared<CursorControllingInputManager>(the_cursor_listener());
464- else
465- return std::make_shared<mi::NullInputManager>();
466- });
467-}
468-
469 std::shared_ptr<droidinput::EventHubInterface>
470 mir::DefaultServerConfiguration::the_event_hub()
471 {
472@@ -289,16 +246,6 @@
473 });
474 }
475
476-std::shared_ptr<mia::InputThread>
477-mir::DefaultServerConfiguration::the_input_reader_thread()
478-{
479- return input_reader_thread(
480- [this]()
481- {
482- return std::make_shared<mia::CommonInputThread>("Mir/InputReader", new droidinput::InputReaderThread(the_input_reader()));
483- });
484-}
485-
486 std::shared_ptr<droidinput::InputListenerInterface>
487 mir::DefaultServerConfiguration::the_input_translator()
488 {
489@@ -415,20 +362,38 @@
490 }
491
492 std::shared_ptr<mi::InputManager>
493-mir::DefaultServerConfiguration::the_new_input_manager()
494+mir::DefaultServerConfiguration::the_input_manager()
495 {
496- return new_input_manager(
497+ // As the input configuration is structured now, if there is no
498+ // InputReader (as in the nested case) there will be nothing to instate
499+ // and keep alive the cursor and its controller.
500+ // We use the CursorControllingInputManager for this purpose.
501+ struct CursorControllingInputManager : public mi::NullInputManager
502+ {
503+ CursorControllingInputManager(
504+ std::shared_ptr<mi::CursorListener> const& cursor_listener)
505+ : cursor_listener(cursor_listener)
506+ {
507+ }
508+
509+ std::shared_ptr<mi::CursorListener> const cursor_listener;
510+ };
511+
512+ return input_manager(
513 [this]() -> std::shared_ptr<mi::InputManager>
514 {
515 auto const options = the_options();
516- bool input_reading_required =
517- options->get<bool>(options::enable_input_opt) &&
518- !options->is_set(options::host_socket_opt);
519+ bool input_opt = options->get<bool>(options::enable_input_opt);
520+ bool input_reading_required = input_opt && !options->is_set(options::host_socket_opt);
521 // TODO nested input handling (== host_socket) should fold into a platform
522
523 if (input_reading_required)
524 {
525- auto ret = std::make_shared<mi::DefaultInputManager>(the_input_reading_multiplexer());
526+ if (options->get<std::string>(options::legacy_input_report_opt) == options::log_opt_value)
527+ mr::legacy_input::initialize(the_logger());
528+
529+ auto ret = std::make_shared<mi::DefaultInputManager>(
530+ the_input_reading_multiplexer(), the_input_reader(), the_event_hub());
531
532 auto platform = the_input_platform();
533 if (platform)
534
535=== modified file 'src/server/input/default_input_manager.cpp'
536--- src/server/input/default_input_manager.cpp 2015-04-16 18:50:58 +0000
537+++ src/server/input/default_input_manager.cpp 2015-04-28 11:14:24 +0000
538@@ -17,6 +17,8 @@
539 */
540
541 #include "default_input_manager.h"
542+#include "android/input_reader_dispatchable.h"
543+
544 #include "mir/input/platform.h"
545 #include "mir/dispatch/action_queue.h"
546 #include "mir/dispatch/multiplexing_dispatchable.h"
547@@ -30,9 +32,12 @@
548 #include <mutex>
549
550 namespace mi = mir::input;
551+namespace mia = mi::android;
552
553-mi::DefaultInputManager::DefaultInputManager(std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer)
554- : multiplexer{multiplexer}, queue{std::make_shared<mir::dispatch::ActionQueue>()}, state{State::stopped}
555+mi::DefaultInputManager::DefaultInputManager(std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,
556+ std::shared_ptr<droidinput::InputReaderInterface> const& reader,
557+ std::shared_ptr<droidinput::EventHubInterface> const& event_hub)
558+ : multiplexer{multiplexer}, legacy_dispatchable{std::make_shared<mia::InputReaderDispatchable>(event_hub, reader)}, queue{std::make_shared<mir::dispatch::ActionQueue>()}, state{State::stopped}
559 {
560 }
561
562@@ -67,17 +72,24 @@
563 if (state == State::running)
564 return;
565
566+ state = State::running;
567+
568 multiplexer->add_watch(queue);
569-
570- state = State::running;
571+ multiplexer->add_watch(legacy_dispatchable);
572+
573+ legacy_dispatchable->start();
574+
575 queue->enqueue([this]()
576 {
577- mir::set_thread_name("Mir/Input");
578- for (auto const& platform : platforms)
579- {
580- platform->start();
581- multiplexer->add_watch(platform->dispatchable());
582- }
583+ mir::set_thread_name("Mir/InputReader");
584+ for (auto const& platform : platforms)
585+ {
586+ platform->start();
587+ multiplexer->add_watch(platform->dispatchable());
588+ }
589+ // TODO: Udev monitoring is still not separated yet - an initial scan is necessary to open
590+ // devices, this will be triggered through the first call to dispatch->InputReader->loopOnce.
591+ legacy_dispatchable->dispatch(dispatch::FdEvent::readable);
592 });
593
594 input_thread = std::make_unique<dispatch::SimpleDispatchThread>(
595@@ -115,5 +127,6 @@
596
597 input_thread.reset();
598
599+ multiplexer->remove_watch(legacy_dispatchable);
600 multiplexer->remove_watch(queue);
601 }
602
603=== modified file 'src/server/input/default_input_manager.h'
604--- src/server/input/default_input_manager.h 2015-04-14 17:06:33 +0000
605+++ src/server/input/default_input_manager.h 2015-04-28 11:14:24 +0000
606@@ -25,6 +25,13 @@
607 #include <thread>
608 #include <atomic>
609
610+// TODO after turning into a platform
611+namespace android
612+{
613+class InputReaderInterface;
614+class EventHubInterface;
615+}
616+namespace droidinput = android;
617 namespace mir
618 {
619 namespace dispatch
620@@ -35,6 +42,10 @@
621 }
622 namespace input
623 {
624+namespace android
625+{
626+class InputReaderDispatchable;
627+}
628 class Platform;
629 class InputEventHandlerRegister;
630 class InputDeviceRegistry;
631@@ -42,7 +53,9 @@
632 class DefaultInputManager : public InputManager
633 {
634 public:
635- DefaultInputManager(std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer);
636+ DefaultInputManager(std::shared_ptr<dispatch::MultiplexingDispatchable> const& multiplexer,
637+ std::shared_ptr<droidinput::InputReaderInterface> const& reader,
638+ std::shared_ptr<droidinput::EventHubInterface> const& event_hub);
639 ~DefaultInputManager();
640 void add_platform(std::shared_ptr<Platform> const& platform) override;
641 void start() override;
642@@ -50,6 +63,7 @@
643 private:
644 std::vector<std::shared_ptr<Platform>> platforms;
645 std::shared_ptr<dispatch::MultiplexingDispatchable> const multiplexer;
646+ std::shared_ptr<input::android::InputReaderDispatchable> const legacy_dispatchable;
647 std::shared_ptr<dispatch::ActionQueue> const queue;
648 std::unique_ptr<dispatch::SimpleDispatchThread> input_thread;
649
650
651=== modified file 'src/server/run_mir.cpp'
652--- src/server/run_mir.cpp 2015-04-14 17:06:33 +0000
653+++ src/server/run_mir.cpp 2015-04-28 11:14:24 +0000
654@@ -32,6 +32,8 @@
655 #include <csignal>
656 #include <cstdlib>
657 #include <cassert>
658+#include <sys/types.h>
659+#include <unistd.h>
660
661 namespace
662 {
663@@ -123,6 +125,6 @@
664 if (!termination_exception)
665 {
666 termination_exception = std::current_exception();
667- raise(SIGTERM);
668+ kill(getpid(), SIGTERM);
669 }
670 }
671
672=== modified file 'src/server/symbols.map'
673--- src/server/symbols.map 2015-04-16 18:50:58 +0000
674+++ src/server/symbols.map 2015-04-28 11:14:24 +0000
675@@ -564,7 +564,6 @@
676 mir::DefaultServerConfiguration::the_input_platform*;
677 mir::DefaultServerConfiguration::the_input_reader*;
678 mir::DefaultServerConfiguration::the_input_reader_policy*;
679- mir::DefaultServerConfiguration::the_input_reader_thread*;
680 mir::DefaultServerConfiguration::the_input_reading_multiplexer*;
681 mir::DefaultServerConfiguration::the_input_region*;
682 mir::DefaultServerConfiguration::the_input_registrar*;
683@@ -579,7 +578,6 @@
684 mir::DefaultServerConfiguration::the_main_loop*;
685 mir::DefaultServerConfiguration::the_mediating_display_changer*;
686 mir::DefaultServerConfiguration::the_message_processor_report*;
687- mir::DefaultServerConfiguration::the_new_input_manager*;
688 mir::DefaultServerConfiguration::the_options*;
689 mir::DefaultServerConfiguration::the_pixel_buffer*;
690 mir::DefaultServerConfiguration::the_placement_strategy*;
691
692=== added file 'tests/include/mir_test_doubles/mock_event_hub.h'
693--- tests/include/mir_test_doubles/mock_event_hub.h 1970-01-01 00:00:00 +0000
694+++ tests/include/mir_test_doubles/mock_event_hub.h 2015-04-28 11:14:24 +0000
695@@ -0,0 +1,69 @@
696+/*
697+ * Copyright © 2015 Canonical Ltd.
698+ *
699+ * This program is free software: you can redistribute it and/or modify
700+ * it under the terms of the GNU General Public License version 3 as
701+ * published by the Free Software Foundation.
702+ *
703+ * This program is distributed in the hope that it will be useful,
704+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
705+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
706+ * GNU General Public License for more details.
707+ *
708+ * You should have received a copy of the GNU General Public License
709+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
710+ *
711+ * Authored by: Andreas Pokorny <andreas.pokorny@gmail.com>
712+ */
713+
714+#ifndef MIR_TEST_DOUBLES_MOCK_EVENT_HUB_H_
715+#define MIR_TEST_DOUBLES_MOCK_EVENT_HUB_H_
716+
717+#include <EventHub.h>
718+#include <gtest/gtest.h>
719+#include <gmock/gmock.h>
720+
721+namespace mir
722+{
723+namespace test
724+{
725+namespace doubles
726+{
727+
728+struct MockEventHub : public droidinput::EventHubInterface
729+{
730+ MOCK_CONST_METHOD1(getDeviceClasses, uint32_t(int32_t));
731+ MOCK_CONST_METHOD1(getDeviceIdentifier, droidinput::InputDeviceIdentifier(int32_t));
732+ MOCK_CONST_METHOD2(getConfiguration, void(int32_t, droidinput::PropertyMap*));
733+ MOCK_CONST_METHOD3(getAbsoluteAxisInfo, droidinput::status_t(int32_t, int, droidinput::RawAbsoluteAxisInfo*));
734+ MOCK_CONST_METHOD2(hasRelativeAxis, bool(int32_t, int));
735+ MOCK_CONST_METHOD2(hasInputProperty, bool(int32_t, int));
736+ MOCK_CONST_METHOD5(mapKey, droidinput::status_t(int32_t, int32_t, int32_t, int32_t*, uint32_t*));
737+ MOCK_CONST_METHOD3(mapAxis, droidinput::status_t(int32_t, int32_t, droidinput::AxisInfo*));
738+ MOCK_METHOD1(setExcludedDevices, void(droidinput::Vector<droidinput::String8> const&));
739+ MOCK_METHOD2(getEvents, size_t(droidinput::RawEvent*, size_t));
740+ MOCK_CONST_METHOD2(getScanCodeState, int32_t(int32_t, int32_t));
741+ MOCK_CONST_METHOD2(getKeyCodeState, int32_t(int32_t, int32_t));
742+ MOCK_CONST_METHOD2(getSwitchState, int32_t(int32_t, int32_t));
743+ MOCK_CONST_METHOD3(getAbsoluteAxisValue, droidinput::status_t(int32_t, int32_t, int32_t*));
744+ MOCK_CONST_METHOD4(markSupportedKeyCodes, bool(int32_t, size_t, int32_t const*, uint8_t*));
745+ MOCK_CONST_METHOD2(hasScanCode, bool(int32_t, int32_t));
746+ MOCK_CONST_METHOD2(hasLed, bool(int32_t, int32_t));
747+ MOCK_METHOD3(setLedState, void(int32_t, int32_t, bool));
748+ MOCK_CONST_METHOD2(getVirtualKeyDefinitions, void(int32_t, droidinput::Vector<droidinput::VirtualKeyDefinition>&));
749+ MOCK_CONST_METHOD1(getKeyCharacterMap, droidinput::sp<droidinput::KeyCharacterMap>(int32_t));
750+ MOCK_METHOD2(setKeyboardLayoutOverlay, bool(int32_t, const droidinput::sp<droidinput::KeyCharacterMap>&));
751+ MOCK_METHOD2(vibrate, void(int32_t, std::chrono::nanoseconds));
752+ MOCK_METHOD1(cancelVibrate, void(int32_t));
753+ MOCK_METHOD0(requestReopenDevices, void());
754+ MOCK_METHOD0(wake, void());
755+ MOCK_METHOD1(wakeIn, void(int32_t));
756+ MOCK_METHOD1(dump, void(droidinput::String8&));
757+ MOCK_METHOD0(monitor, void());
758+ MOCK_METHOD0(flush, void());
759+ MOCK_METHOD0(fd, mir::Fd());
760+};
761+}
762+}
763+}
764+#endif
765
766=== added file 'tests/include/mir_test_doubles/mock_input_reader.h'
767--- tests/include/mir_test_doubles/mock_input_reader.h 1970-01-01 00:00:00 +0000
768+++ tests/include/mir_test_doubles/mock_input_reader.h 2015-04-28 11:14:24 +0000
769@@ -0,0 +1,58 @@
770+/*
771+ * Copyright © 2015 Canonical Ltd.
772+ *
773+ * This program is free software: you can redistribute it and/or modify
774+ * it under the terms of the GNU General Public License version 3 as
775+ * published by the Free Software Foundation.
776+ *
777+ * This program is distributed in the hope that it will be useful,
778+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
779+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
780+ * GNU General Public License for more details.
781+ *
782+ * You should have received a copy of the GNU General Public License
783+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
784+ *
785+ * Authored by: Andreas Pokorny <andreas.pokorny@gmail.com>
786+ */
787+
788+#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_READER_H_
789+#define MIR_TEST_DOUBLES_MOCK_INPUT_READER_H_
790+
791+#include <InputReader.h>
792+#include <gtest/gtest.h>
793+#include <gmock/gmock.h>
794+
795+namespace mir
796+{
797+namespace test
798+{
799+namespace doubles
800+{
801+struct MockInputReader : public droidinput::InputReaderInterface
802+{
803+public:
804+ MOCK_METHOD1(dump, void(droidinput::String8& dump));
805+ MOCK_METHOD0(monitor, void());
806+ MOCK_METHOD0(loopOnce, void());
807+ MOCK_METHOD1(getInputDevices, void(droidinput::Vector<droidinput::InputDeviceInfo>& outInputDevices));
808+ MOCK_METHOD3(getScanCodeState, int32_t(int32_t deviceId, uint32_t sourceMask,
809+ int32_t scanCode));
810+ MOCK_METHOD3(getKeyCodeState, int32_t(int32_t deviceId, uint32_t sourceMask,
811+ int32_t keyCode));
812+ MOCK_METHOD3(getSwitchState, int32_t(int32_t deviceId, uint32_t sourceMask,
813+ int32_t sw));
814+ MOCK_METHOD5(hasKeys, bool(int32_t deviceId, uint32_t sourceMask,
815+ size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags));
816+ MOCK_METHOD1(requestRefreshConfiguration,void (uint32_t changes));
817+
818+ MOCK_METHOD5(vibrate, void(int32_t deviceId, const std::chrono::nanoseconds* pattern, size_t patternSize,
819+ ssize_t repeat, int32_t token));
820+ MOCK_METHOD2(cancelVibrate, void(int32_t deviceId, int32_t token));
821+};
822+
823+}
824+}
825+}
826+
827+#endif
828
829=== modified file 'tests/unit-tests/android_input/test_eventhub.cpp'
830--- tests/unit-tests/android_input/test_eventhub.cpp 2015-04-16 08:09:52 +0000
831+++ tests/unit-tests/android_input/test_eventhub.cpp 2015-04-28 11:14:24 +0000
832@@ -35,8 +35,7 @@
833
834 namespace mi = mir::input;
835
836-// EventHub still blocks on getEvents
837-TEST(DISABLED_EventHub, does_not_block_on_get_events)
838+TEST(EventHub, does_not_block_on_get_events)
839 {
840 mir_test_framework::UdevEnvironment empty_env;
841 auto hub = android::sp<android::EventHub>{new android::EventHub{mir::report::null_input_report()}};
842@@ -68,11 +67,12 @@
843 std::thread reader{
844 [hub,event_hub_triggered]
845 {
846- android::RawEvent buffer[10];
847- memset(buffer, 0, sizeof(buffer));
848- hub->getEvents(buffer,10);
849+ struct epoll_event pending_event;
850+ std::memset(&pending_event, 0, sizeof pending_event);
851+ epoll_wait(hub->fd(), &pending_event, 1, -1);
852
853- event_hub_triggered->wake_up_everyone();
854+ if (pending_event.data.u32 == android::EventHub::EPOLL_ID_TIMER)
855+ event_hub_triggered->wake_up_everyone();
856 }};
857
858 reader.detach();
859
860=== modified file 'tests/unit-tests/input/android/CMakeLists.txt'
861--- tests/unit-tests/input/android/CMakeLists.txt 2015-04-14 17:06:33 +0000
862+++ tests/unit-tests/input/android/CMakeLists.txt 2015-04-28 11:14:24 +0000
863@@ -3,7 +3,7 @@
864 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_pointer_controller.cpp
865 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_lexicon.cpp
866 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_reader_policy.cpp
867- ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_manager.cpp
868+ ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_channel_factory.cpp
869 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_dispatcher.cpp
870 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_communication_package.cpp
871 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_application_handle.cpp
872@@ -12,6 +12,7 @@
873 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_sender.cpp
874 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_target_enumerator.cpp
875 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_registrar.cpp
876+ ${CMAKE_CURRENT_SOURCE_DIR}/test_input_reader_dispatchable.cpp
877 ${CMAKE_CURRENT_SOURCE_DIR}/test_input_translator.cpp
878 )
879
880
881=== renamed file 'tests/unit-tests/input/android/test_android_input_manager.cpp' => 'tests/unit-tests/input/android/test_android_input_channel_factory.cpp'
882--- tests/unit-tests/input/android/test_android_input_manager.cpp 2015-04-16 08:09:52 +0000
883+++ tests/unit-tests/input/android/test_android_input_channel_factory.cpp 2015-04-28 11:14:24 +0000
884@@ -1,5 +1,5 @@
885 /*
886- * Copyright © 2013 Canonical Ltd.
887+ * Copyright © 2013-2015 Canonical Ltd.
888 *
889 * This program is free software: you can redistribute it and/or modify it
890 * under the terms of the GNU General Public License version 3,
891@@ -16,140 +16,17 @@
892 * Authored by: Robert Carr <robert.carr@canonical.com>
893 */
894
895-#include "src/server/input/android/android_input_manager.h"
896-#include "src/server/input/android/android_input_thread.h"
897-#include "src/server/input/android/android_input_constants.h"
898 #include "src/server/input/android/android_input_channel.h"
899 #include "src/server/input/android/input_channel_factory.h"
900
901-#include "mir/input/input_channel.h"
902-
903-#include "mir_test/fake_shared.h"
904-#include "mir_test_doubles/stub_input_channel.h"
905-
906-#include <EventHub.h>
907-#include <utils/StrongPointer.h>
908-
909 #include <gtest/gtest.h>
910 #include <gmock/gmock.h>
911
912 #include <initializer_list>
913
914-namespace droidinput = android;
915-
916-namespace mi = mir::input;
917 namespace mia = mir::input::android;
918-namespace mt = mir::test;
919-namespace mtd = mt::doubles;
920-
921-// Mock objects
922-namespace
923-{
924-
925-struct MockEventHub : public droidinput::EventHubInterface
926-{
927- MOCK_CONST_METHOD1(getDeviceClasses, uint32_t(int32_t));
928- MOCK_CONST_METHOD1(getDeviceIdentifier, droidinput::InputDeviceIdentifier(int32_t));
929- MOCK_CONST_METHOD2(getConfiguration, void(int32_t, droidinput::PropertyMap*));
930- MOCK_CONST_METHOD3(getAbsoluteAxisInfo, droidinput::status_t(int32_t, int, droidinput::RawAbsoluteAxisInfo*));
931- MOCK_CONST_METHOD2(hasRelativeAxis, bool(int32_t, int));
932- MOCK_CONST_METHOD2(hasInputProperty, bool(int32_t, int));
933- MOCK_CONST_METHOD5(mapKey, droidinput::status_t(int32_t, int32_t, int32_t, int32_t*, uint32_t*));
934- MOCK_CONST_METHOD3(mapAxis, droidinput::status_t(int32_t, int32_t, droidinput::AxisInfo*));
935- MOCK_METHOD1(setExcludedDevices, void(droidinput::Vector<droidinput::String8> const&));
936- MOCK_METHOD2(getEvents, size_t(droidinput::RawEvent*, size_t));
937- MOCK_CONST_METHOD2(getScanCodeState, int32_t(int32_t, int32_t));
938- MOCK_CONST_METHOD2(getKeyCodeState, int32_t(int32_t, int32_t));
939- MOCK_CONST_METHOD2(getSwitchState, int32_t(int32_t, int32_t));
940- MOCK_CONST_METHOD3(getAbsoluteAxisValue, droidinput::status_t(int32_t, int32_t, int32_t*));
941- MOCK_CONST_METHOD4(markSupportedKeyCodes, bool(int32_t, size_t, int32_t const*, uint8_t*));
942- MOCK_CONST_METHOD2(hasScanCode, bool(int32_t, int32_t));
943- MOCK_CONST_METHOD2(hasLed, bool(int32_t, int32_t));
944- MOCK_METHOD3(setLedState, void(int32_t, int32_t, bool));
945- MOCK_CONST_METHOD2(getVirtualKeyDefinitions, void(int32_t, droidinput::Vector<droidinput::VirtualKeyDefinition>&));
946- MOCK_CONST_METHOD1(getKeyCharacterMap, droidinput::sp<droidinput::KeyCharacterMap>(int32_t));
947- MOCK_METHOD2(setKeyboardLayoutOverlay, bool(int32_t, const droidinput::sp<droidinput::KeyCharacterMap>&));
948- MOCK_METHOD2(vibrate, void(int32_t, std::chrono::nanoseconds));
949- MOCK_METHOD1(cancelVibrate, void(int32_t));
950- MOCK_METHOD0(requestReopenDevices, void());
951- MOCK_METHOD0(wake, void());
952- MOCK_METHOD1(wakeIn, void(int32_t));
953- MOCK_METHOD1(dump, void(droidinput::String8&));
954- MOCK_METHOD0(monitor, void());
955- MOCK_METHOD0(flush, void());
956- MOCK_METHOD0(fd, mir::Fd());
957-};
958-
959-struct MockInputThread : public mia::InputThread
960-{
961- MOCK_METHOD0(start, void());
962- MOCK_METHOD0(request_stop, void());
963- MOCK_METHOD0(join, void());
964-};
965-
966-}
967-
968-// Test fixture
969-namespace
970-{
971-
972-struct AndroidInputManagerSetup : public testing::Test
973-{
974- std::shared_ptr<MockEventHub> event_hub = std::make_shared<MockEventHub>();
975- std::shared_ptr<MockInputThread> reader_thread = std::make_shared<MockInputThread>();
976-
977- void setup_start_expectations()
978- {
979- testing::InSequence seq;
980-
981- EXPECT_CALL(*event_hub, flush());
982- EXPECT_CALL(*reader_thread, start());
983- }
984-
985- void setup_stop_expectations()
986- {
987- testing::InSequence seq;
988-
989- EXPECT_CALL(*reader_thread, request_stop());
990- EXPECT_CALL(*event_hub, wake());
991- EXPECT_CALL(*reader_thread, join());
992- }
993-};
994-
995-}
996-
997-TEST_F(AndroidInputManagerSetup, starts_and_stops_reader)
998-{
999- using namespace ::testing;
1000-
1001- setup_start_expectations();
1002- setup_stop_expectations();
1003-
1004- mia::InputManager manager(event_hub, reader_thread);
1005-
1006- manager.start();
1007- manager.stop();
1008-
1009- // The input manager is unconditionally stopped at destruction.
1010- Mock::VerifyAndClearExpectations(reader_thread.get());
1011- Mock::VerifyAndClearExpectations(event_hub.get());
1012-
1013- setup_stop_expectations();
1014-}
1015-
1016-TEST_F(AndroidInputManagerSetup, stops_reader_at_destruction)
1017-{
1018- using namespace ::testing;
1019-
1020- setup_start_expectations();
1021- setup_stop_expectations();
1022-
1023- mia::InputManager manager(event_hub, reader_thread);
1024-
1025- manager.start();
1026-}
1027-
1028-TEST_F(AndroidInputManagerSetup, channel_factory_returns_input_channel_with_fds)
1029+
1030+TEST(AndroidInputChannelFactory, channel_factory_returns_input_channel_with_fds)
1031 {
1032 mia::InputChannelFactory factory;
1033
1034
1035=== added file 'tests/unit-tests/input/android/test_input_reader_dispatchable.cpp'
1036--- tests/unit-tests/input/android/test_input_reader_dispatchable.cpp 1970-01-01 00:00:00 +0000
1037+++ tests/unit-tests/input/android/test_input_reader_dispatchable.cpp 2015-04-28 11:14:24 +0000
1038@@ -0,0 +1,51 @@
1039+/*
1040+ * Copyright © 2015 Canonical Ltd.
1041+ *
1042+ * This program is free software: you can redistribute it and/or modify
1043+ * it under the terms of the GNU General Public License version 3 as
1044+ * published by the Free Software Foundation.
1045+ *
1046+ * This program is distributed in the hope that it will be useful,
1047+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1048+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1049+ * GNU General Public License for more details.
1050+ *
1051+ * You should have received a copy of the GNU General Public License
1052+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1053+ *
1054+ * Authored by: Andreas Pokorny <andreas.pokorny@gmail.com>
1055+ */
1056+
1057+#include "src/server/input/android/input_reader_dispatchable.h"
1058+
1059+#include "mir_test_doubles/mock_event_hub.h"
1060+#include "mir_test_doubles/mock_input_reader.h"
1061+#include "InputReader.h"
1062+
1063+namespace mtd = mir::test::doubles;
1064+namespace mia = mir::input::android;
1065+namespace droidinput = android;
1066+namespace
1067+{
1068+struct TestInputReaderDispatchable : public ::testing::Test
1069+{
1070+ std::shared_ptr<mtd::MockInputReader> reader = std::make_shared<mtd::MockInputReader>();
1071+ std::shared_ptr<mtd::MockEventHub> hub = std::make_shared<mtd::MockEventHub>();
1072+ mia::InputReaderDispatchable dispatchable{hub, reader};
1073+
1074+};
1075+}
1076+
1077+TEST_F(TestInputReaderDispatchable,loops_on_readable)
1078+{
1079+ EXPECT_CALL(*reader, loopOnce());
1080+
1081+ EXPECT_TRUE(dispatchable.dispatch(mir::dispatch::FdEvent::readable));
1082+}
1083+
1084+TEST_F(TestInputReaderDispatchable, false_on_error)
1085+{
1086+ EXPECT_CALL(*reader, loopOnce()).Times(0);
1087+
1088+ EXPECT_FALSE(dispatchable.dispatch(mir::dispatch::FdEvent::error));
1089+}
1090
1091=== modified file 'tests/unit-tests/input/test_default_input_manager.cpp'
1092--- tests/unit-tests/input/test_default_input_manager.cpp 2015-04-14 17:06:33 +0000
1093+++ tests/unit-tests/input/test_default_input_manager.cpp 2015-04-28 11:14:24 +0000
1094@@ -22,11 +22,15 @@
1095 #include "mir_test/signal.h"
1096 #include "mir_test/fake_shared.h"
1097 #include "mir_test_doubles/mock_input_platform.h"
1098+#include "mir_test_doubles/mock_event_hub.h"
1099+#include "mir_test_doubles/mock_input_reader.h"
1100
1101 #include "mir/input/platform.h"
1102 #include "mir/dispatch/multiplexing_dispatchable.h"
1103 #include "mir/dispatch/action_queue.h"
1104
1105+#include <sys/eventfd.h>
1106+
1107 #include <gtest/gtest.h>
1108 #include <gmock/gmock.h>
1109
1110@@ -43,10 +47,17 @@
1111 md::MultiplexingDispatchable multiplexer;
1112 md::ActionQueue platform_dispatchable;
1113 NiceMock<mtd::MockInputPlatform> platform;
1114- mir::input::DefaultInputManager input_manager{mt::fake_shared(multiplexer)};
1115+ mir::Fd event_hub_fd{eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK)};
1116+ NiceMock<mtd::MockEventHub> event_hub;
1117+ NiceMock<mtd::MockInputReader> reader;
1118+ mir::input::DefaultInputManager input_manager{mt::fake_shared(multiplexer), mt::fake_shared(reader), mt::fake_shared(event_hub)};
1119
1120 DefaultInputManagerTest()
1121 {
1122+ ON_CALL(event_hub, fd())
1123+ .WillByDefault(Return(event_hub_fd));
1124+ ON_CALL(platform, dispatchable())
1125+ .WillByDefault(Return(mt::fake_shared(platform_dispatchable)));
1126 ON_CALL(platform, dispatchable())
1127 .WillByDefault(Return(mt::fake_shared(platform_dispatchable)));
1128 }
1129@@ -68,6 +79,33 @@
1130
1131 }
1132
1133+TEST_F(DefaultInputManagerTest, flushes_event_hub_before_anything_to_fulfill_legacy_tests)
1134+{
1135+ testing::InSequence seq;
1136+ EXPECT_CALL(event_hub, flush()).Times(1);
1137+ EXPECT_CALL(platform, start()).Times(1);
1138+ EXPECT_CALL(platform, dispatchable()).Times(2);
1139+ EXPECT_CALL(platform, stop()).Times(1);
1140+
1141+ input_manager.add_platform(mt::fake_shared(platform));
1142+ input_manager.start();
1143+ Mock::VerifyAndClearExpectations(&event_hub);
1144+
1145+ EXPECT_TRUE(wait_for_multiplexer_dispatch());
1146+}
1147+
1148+TEST_F(DefaultInputManagerTest, flushes_then_loops_once_to_initiate_device_scan_after_start)
1149+{
1150+ testing::InSequence seq;
1151+ EXPECT_CALL(event_hub, flush()).Times(1);
1152+ EXPECT_CALL(reader, loopOnce()).Times(1);
1153+
1154+ input_manager.start();
1155+ Mock::VerifyAndClearExpectations(&event_hub);
1156+
1157+ EXPECT_TRUE(wait_for_multiplexer_dispatch());
1158+}
1159+
1160 TEST_F(DefaultInputManagerTest, starts_platforms_on_start)
1161 {
1162 EXPECT_CALL(platform, start()).Times(1);

Subscribers

People subscribed via source and target branches