Merge lp:~thomas-voss/location-service/allow-for-disabling-providers into lp:location-service/trunk

Proposed by Thomas Voß on 2014-11-13
Status: Superseded
Proposed branch: lp:~thomas-voss/location-service/allow-for-disabling-providers
Merge into: lp:location-service/trunk
Diff against target: 470 lines (+276/-12)
8 files modified
include/location_service/com/ubuntu/location/provider.h (+27/-0)
include/location_service/com/ubuntu/location/providers/remote/interface.h (+2/-0)
src/location_service/com/ubuntu/location/engine.cpp (+31/-11)
src/location_service/com/ubuntu/location/provider.cpp (+32/-0)
src/location_service/com/ubuntu/location/providers/remote/provider.cpp (+56/-0)
src/location_service/com/ubuntu/location/providers/remote/provider.h (+6/-0)
tests/engine_test.cpp (+82/-1)
tests/provider_test.cpp (+40/-0)
To merge this branch: bzr merge lp:~thomas-voss/location-service/allow-for-disabling-providers
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing on 2014-11-13
Loïc Minier 2014-11-13 Approve on 2014-11-13
Review via email: mp+241707@code.launchpad.net

This proposal has been superseded by a proposal from 2015-01-12.

Commit Message

Allow for enabling/disabling providers.
Wire up engine state changes to enabling/disabling of providers.

Description of the Change

Allow for enabling/disabling providers.
Wire up engine state changes to enabling/disabling of providers.

To post a comment you must log in.
Loïc Minier (lool) wrote :

Looks really clean; I see the default is enabled, I guess I need to test that config updates actually trigger enabling/disabling as designed

Loïc Minier (lool) :
review: Approve
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
153. By Thomas Voß on 2015-01-12

Merge pre-requisite branch.
Fix FTBFS in test cases.

154. By Thomas Voß on 2015-01-21

Refactor the change to make it ABI stable.

155. By Thomas Voß on 2015-01-21

Make enable and disable non-virtual for now.

156. By Thomas Voß on 2015-01-22

Make sure that the provider is really stopped when disabling it.

157. By Thomas Voß on 2015-01-23

Only stop provider updates if they have been running.

158. By Thomas Voß on 2015-01-23

Anything lt 0 means: Provider is disabled.

159. By Thomas Voß on 2015-01-23

Make sure that we only enable providers that really should be enabled.

160. By Thomas Voß on 2015-01-23

Need this as context of the lamdba.

161. By Thomas Voß on 2015-01-23

Revert auto-enablement.

162. By Thomas Voß on 2015-01-23

A minor niggle.

163. By Thomas Voß on 2015-01-23

Merge pre-req branch.

164. By Thomas Voß on 2015-01-25

Make sure that newly added providers are disabled, too.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/location_service/com/ubuntu/location/provider.h'
2--- include/location_service/com/ubuntu/location/provider.h 2013-12-30 08:06:11 +0000
3+++ include/location_service/com/ubuntu/location/provider.h 2014-11-13 16:49:18 +0000
4@@ -82,11 +82,27 @@
5 public:
6 typedef std::shared_ptr<Controller> Ptr;
7
8+ /** @brief Enumerates known states of a controller/provider. */
9+ enum class State
10+ {
11+ disabled, ///< The provider is disabled.
12+ enabled ///< The provider is enabled.
13+ };
14+
15 virtual ~Controller() = default;
16 Controller(const Controller&) = delete;
17 Controller& operator=(const Controller&) = delete;
18
19 /**
20+ * @brief Returns the getable/setable/observable state of the controller.
21+ *
22+ * If the controller is in state disabled, all calls to start* or stop*
23+ * have no effect and subsequent calls to is*running will return false.
24+ *
25+ */
26+ virtual core::Property<State>& state();
27+
28+ /**
29 * @brief Request to start position updates if not already running.
30 */
31 virtual void start_position_updates();
32@@ -140,6 +156,7 @@
33
34 private:
35 Provider& instance;
36+ core::Property<State> current_state;
37 std::atomic<int> position_updates_counter;
38 std::atomic<int> heading_updates_counter;
39 std::atomic<int> velocity_updates_counter;
40@@ -229,6 +246,16 @@
41 virtual Updates& mutable_updates();
42
43 /**
44+ * @brief Disables the provider, empty by default.
45+ */
46+ virtual void disable();
47+
48+ /**
49+ * @brief Enables the provider, empty by default.
50+ */
51+ virtual void enable();
52+
53+ /**
54 * @brief Implementation-specific, empty by default.
55 */
56 virtual void start_position_updates();
57
58=== modified file 'include/location_service/com/ubuntu/location/providers/remote/interface.h'
59--- include/location_service/com/ubuntu/location/providers/remote/interface.h 2014-09-12 15:04:21 +0000
60+++ include/location_service/com/ubuntu/location/providers/remote/interface.h 2014-11-13 16:49:18 +0000
61@@ -66,6 +66,8 @@
62 // Called by the engine whenever the reference velocity changed.
63 DBUS_CPP_METHOD_DEF(OnReferenceVelocityChanged, remote::Interface)
64
65+ DBUS_CPP_METHOD_DEF(Disable, remote::Interface)
66+ DBUS_CPP_METHOD_DEF(Enable, remote::Interface)
67 DBUS_CPP_METHOD_DEF(StartPositionUpdates, remote::Interface)
68 DBUS_CPP_METHOD_DEF(StopPositionUpdates, remote::Interface)
69 DBUS_CPP_METHOD_DEF(StartHeadingUpdates, remote::Interface)
70
71=== modified file 'src/location_service/com/ubuntu/location/engine.cpp'
72--- src/location_service/com/ubuntu/location/engine.cpp 2014-10-03 20:00:09 +0000
73+++ src/location_service/com/ubuntu/location/engine.cpp 2014-11-13 16:49:18 +0000
74@@ -31,21 +31,41 @@
75 std::runtime_error("Cannot construct an engine given a null ProviderSelectionPolicy");
76
77 // Setup behavior in case of configuration changes.
78+ configuration.satellite_based_positioning_state.changed().connect([this](const SatelliteBasedPositioningState& state)
79+ {
80+ for_each_provider([state](const Provider::Ptr& provider)
81+ {
82+ if (provider->requires(cul::Provider::Requirements::satellites))
83+ {
84+ switch (state)
85+ {
86+ case SatelliteBasedPositioningState::on:
87+ provider->state_controller()->state() = cul::Provider::Controller::State::enabled;
88+ break;
89+ case SatelliteBasedPositioningState::off:
90+ provider->state_controller()->state() = cul::Provider::Controller::State::disabled;
91+ break;
92+ }
93+ }
94+ });
95+ });
96+
97 configuration.engine_state.changed().connect([this](const Engine::Status& status)
98 {
99- switch (status)
100+ for_each_provider([status](const Provider::Ptr& provider)
101 {
102- case Engine::Status::off:
103- for_each_provider([](const Provider::Ptr& provider)
104+ switch (status)
105 {
106- provider->state_controller()->stop_position_updates();
107- provider->state_controller()->stop_heading_updates();
108- provider->state_controller()->stop_velocity_updates();
109- });
110- break;
111- default:
112- break;
113- }
114+ case Engine::Status::on:
115+ provider->state_controller()->state() = cul::Provider::Controller::State::enabled;
116+ break;
117+ case Engine::Status::off:
118+ provider->state_controller()->state() = cul::Provider::Controller::State::disabled;
119+ break;
120+ default:
121+ break;
122+ }
123+ });
124 });
125 }
126
127
128=== modified file 'src/location_service/com/ubuntu/location/provider.cpp'
129--- src/location_service/com/ubuntu/location/provider.cpp 2014-06-20 07:40:34 +0000
130+++ src/location_service/com/ubuntu/location/provider.cpp 2014-11-13 16:49:18 +0000
131@@ -23,8 +23,16 @@
132
133 namespace cul = com::ubuntu::location;
134
135+core::Property<cul::Provider::Controller::State>& cul::Provider::Controller::state()
136+{
137+ return current_state;
138+}
139+
140 void cul::Provider::Controller::start_position_updates()
141 {
142+ if (current_state == cul::Provider::Controller::State::disabled)
143+ return;
144+
145 if (++position_updates_counter == 1)
146 {
147 instance.start_position_updates();
148@@ -46,6 +54,9 @@
149
150 void cul::Provider::Controller::start_heading_updates()
151 {
152+ if (current_state == cul::Provider::Controller::State::disabled)
153+ return;
154+
155 if (++heading_updates_counter == 1)
156 {
157 instance.start_heading_updates();
158@@ -67,6 +78,9 @@
159
160 void cul::Provider::Controller::start_velocity_updates()
161 {
162+ if (current_state == cul::Provider::Controller::State::disabled)
163+ return;
164+
165 if (++velocity_updates_counter == 1)
166 {
167 instance.start_velocity_updates();
168@@ -88,10 +102,26 @@
169
170 cul::Provider::Controller::Controller(cul::Provider& instance)
171 : instance(instance),
172+ current_state(cul::Provider::Controller::State::enabled),
173 position_updates_counter(0),
174 heading_updates_counter(0),
175 velocity_updates_counter(0)
176 {
177+ current_state.changed().connect([this](cul::Provider::Controller::State state)
178+ {
179+ switch (state)
180+ {
181+ case cul::Provider::Controller::State::disabled:
182+ Controller::instance.disable();
183+ stop_position_updates();
184+ stop_heading_updates();
185+ stop_velocity_updates();
186+ break;
187+ case cul::Provider::Controller::State::enabled:
188+ Controller::instance.enable();
189+ break;
190+ }
191+ });
192 }
193
194 const cul::Provider::Controller::Ptr& cul::Provider::state_controller() const
195@@ -149,6 +179,8 @@
196 {
197 }
198
199+void cul::Provider::disable() {}
200+void cul::Provider::enable() {}
201 void cul::Provider::start_position_updates() {}
202 void cul::Provider::stop_position_updates() {}
203 void cul::Provider::start_heading_updates() {}
204
205=== modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.cpp'
206--- src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2014-10-27 21:58:16 +0000
207+++ src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2014-11-13 16:49:18 +0000
208@@ -348,6 +348,38 @@
209 });
210 }
211
212+void remote::Provider::Stub::disable()
213+{
214+ VLOG(10) << "> " << __PRETTY_FUNCTION__;
215+ std::weak_ptr<Private> wp{d};
216+ Runtime::instance().task.service.post([wp]()
217+ {
218+ auto sp = wp.lock();
219+
220+ if (not sp)
221+ return;
222+
223+ throw_if_error(sp->stub.object->transact_method<remote::Interface::Disable, void>());
224+ });
225+ VLOG(10) << "< " << __PRETTY_FUNCTION__;
226+}
227+
228+void remote::Provider::Stub::enable()
229+{
230+ VLOG(10) << "> " << __PRETTY_FUNCTION__;
231+ std::weak_ptr<Private> wp{d};
232+ Runtime::instance().task.service.post([wp]()
233+ {
234+ auto sp = wp.lock();
235+
236+ if (not sp)
237+ return;
238+
239+ throw_if_error(sp->stub.object->transact_method<remote::Interface::Enable, void>());
240+ });
241+ VLOG(10) << "< " << __PRETTY_FUNCTION__;
242+}
243+
244 void remote::Provider::Stub::start_position_updates()
245 {
246 VLOG(10) << "> " << __PRETTY_FUNCTION__;
247@@ -563,6 +595,20 @@
248 on_reference_velocity_updated(u);
249 });
250
251+ d->skeleton.object->install_method_handler<remote::Interface::Disable>([this](const dbus::Message::Ptr & msg)
252+ {
253+ VLOG(1) << "Disable";
254+ disable();
255+ d->bus->send(dbus::Message::make_method_return(msg));
256+ });
257+
258+ d->skeleton.object->install_method_handler<remote::Interface::Enable>([this](const dbus::Message::Ptr & msg)
259+ {
260+ VLOG(1) << "Enable";
261+ enable();
262+ d->bus->send(dbus::Message::make_method_return(msg));
263+ });
264+
265 d->skeleton.object->install_method_handler<remote::Interface::StartPositionUpdates>([this](const dbus::Message::Ptr & msg)
266 {
267 VLOG(1) << "StartPositionUpdates";
268@@ -656,6 +702,16 @@
269 d->impl->on_reference_heading_updated(heading);
270 }
271
272+void remote::Provider::Skeleton::disable()
273+{
274+ d->impl->state_controller()->state() = location::Provider::Controller::State::disabled;
275+}
276+
277+void remote::Provider::Skeleton::enable()
278+{
279+ d->impl->state_controller()->state() = location::Provider::Controller::State::enabled;
280+}
281+
282 void remote::Provider::Skeleton::start_position_updates()
283 {
284 d->impl->state_controller()->start_position_updates();
285
286=== modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.h'
287--- src/location_service/com/ubuntu/location/providers/remote/provider.h 2014-10-27 21:58:16 +0000
288+++ src/location_service/com/ubuntu/location/providers/remote/provider.h 2014-11-13 16:49:18 +0000
289@@ -69,6 +69,9 @@
290 virtual void on_reference_velocity_updated(const Update<Velocity>& velocity) override;
291 virtual void on_reference_heading_updated(const Update<Heading>& heading) override;
292
293+ virtual void disable() override;
294+ virtual void enable() override;
295+
296 virtual void start_position_updates() override;
297 virtual void stop_position_updates() override;
298
299@@ -104,6 +107,9 @@
300 virtual void on_reference_velocity_updated(const Update<Velocity>& velocity) override;
301 virtual void on_reference_heading_updated(const Update<Heading>& heading) override;
302
303+ virtual void disable() override;
304+ virtual void enable() override;
305+
306 virtual void start_position_updates() override;
307 virtual void stop_position_updates() override;
308
309
310=== modified file 'tests/engine_test.cpp'
311--- tests/engine_test.cpp 2014-06-01 17:56:58 +0000
312+++ tests/engine_test.cpp 2014-11-13 16:49:18 +0000
313@@ -35,6 +35,10 @@
314 {
315 }
316
317+ MOCK_CONST_METHOD1(requires, bool(const location::Provider::Requirements&));
318+
319+ MOCK_METHOD0(disable, void());
320+ MOCK_METHOD0(enable, void());
321 MOCK_METHOD0(stop_position_updates, void());
322 MOCK_METHOD0(stop_velocity_updates, void());
323 MOCK_METHOD0(stop_heading_updates, void());
324@@ -137,7 +141,7 @@
325 engine.updates.reference_velocity = location::Update<location::Velocity>{};
326 }
327
328-TEST(Engine, switching_the_engine_off_results_in_updates_being_stopped)
329+TEST(Engine, switching_the_engine_off_results_in_providers_being_disabled_and_updates_being_stopped)
330 {
331 using namespace ::testing;
332
333@@ -150,9 +154,86 @@
334 location::Engine engine{selection_policy};
335 engine.add_provider(provider);
336
337+ EXPECT_CALL(*provider, disable()).Times(1);
338 EXPECT_CALL(*provider, stop_position_updates()).Times(1);
339 EXPECT_CALL(*provider, stop_velocity_updates()).Times(1);
340 EXPECT_CALL(*provider, stop_heading_updates()).Times(1);
341
342 engine.configuration.engine_state = location::Engine::Status::off;
343 }
344+
345+TEST(Engine, switching_the_engine_on_after_off_results_in_providers_being_enabled)
346+{
347+ using namespace ::testing;
348+
349+ auto provider = std::make_shared<NiceMock<MockProvider>>();
350+
351+ auto selection_policy = std::make_shared<NiceMock<MockProviderSelectionPolicy>>();
352+ location::Engine engine{selection_policy};
353+ engine.add_provider(provider);
354+
355+ EXPECT_CALL(*provider, disable()).Times(1);
356+ EXPECT_CALL(*provider, enable()).Times(1);
357+
358+ engine.configuration.engine_state = location::Engine::Status::off;
359+ engine.configuration.engine_state = location::Engine::Status::on;
360+}
361+
362+TEST(Engine, switching_satellite_based_positioning_off_disables_providers_requiring_satellites)
363+{
364+ using namespace ::testing;
365+
366+ auto gps_provider = std::make_shared<NiceMock<MockProvider>>();
367+ auto network_provider = std::make_shared<NiceMock<MockProvider>>();
368+
369+ ON_CALL(*gps_provider, requires(Ne(location::Provider::Requirements::satellites)))
370+ .WillByDefault(Return(true));
371+ ON_CALL(*gps_provider, requires(location::Provider::Requirements::satellites))
372+ .WillByDefault(Return(true));
373+ ON_CALL(*network_provider, requires(location::Provider::Requirements::satellites))
374+ .WillByDefault(Return(false));
375+
376+ auto selection_policy = std::make_shared<NiceMock<MockProviderSelectionPolicy>>();
377+ location::Engine engine{selection_policy};
378+ engine.add_provider(gps_provider);
379+ engine.add_provider(network_provider);
380+
381+ // Only the mocked gps provider requiring satellites will be disabled.
382+ EXPECT_CALL(*gps_provider, disable()).Times(1);
383+ // The network based provider will not be disabled.
384+ EXPECT_CALL(*network_provider, disable()).Times(0);
385+
386+ engine.configuration.satellite_based_positioning_state = location::SatelliteBasedPositioningState::off;
387+}
388+
389+TEST(Engine, switching_satellite_based_positioning_on_after_off_disables_and_enables_providers_requiring_satellites)
390+{
391+ using namespace ::testing;
392+
393+ auto gps_provider = std::make_shared<NiceMock<MockProvider>>();
394+ auto network_provider = std::make_shared<NiceMock<MockProvider>>();
395+
396+ ON_CALL(*gps_provider, requires(Ne(location::Provider::Requirements::satellites)))
397+ .WillByDefault(Return(true));
398+ ON_CALL(*gps_provider, requires(location::Provider::Requirements::satellites))
399+ .WillByDefault(Return(true));
400+ ON_CALL(*network_provider, requires(location::Provider::Requirements::satellites))
401+ .WillByDefault(Return(false));
402+
403+ auto selection_policy = std::make_shared<NiceMock<MockProviderSelectionPolicy>>();
404+ location::Engine engine{selection_policy};
405+ engine.add_provider(gps_provider);
406+ engine.add_provider(network_provider);
407+
408+ // Only the mocked gps provider requiring satellites will be disabled.
409+ EXPECT_CALL(*gps_provider, disable()).Times(1);
410+ // Only the mocked gps provider requiring satellites will be disabled.
411+ EXPECT_CALL(*gps_provider, enable()).Times(1);
412+ // The network based provider will not be disabled.
413+ EXPECT_CALL(*network_provider, disable()).Times(0);
414+ // The network based provider will not be disabled.
415+ EXPECT_CALL(*network_provider, enable()).Times(0);
416+
417+ engine.configuration.satellite_based_positioning_state = location::SatelliteBasedPositioningState::off;
418+ engine.configuration.satellite_based_positioning_state = location::SatelliteBasedPositioningState::on;
419+}
420
421=== modified file 'tests/provider_test.cpp'
422--- tests/provider_test.cpp 2014-06-20 07:40:34 +0000
423+++ tests/provider_test.cpp 2014-11-13 16:49:18 +0000
424@@ -186,6 +186,46 @@
425 EXPECT_FALSE(provider.state_controller()->are_velocity_updates_running());
426 }
427
428+TEST(Provider, initial_state_of_controller_is_enabled)
429+{
430+ using namespace ::testing;
431+
432+ NiceMock<MockProvider> p;
433+ EXPECT_EQ(cul::Provider::Controller::State::enabled, p.state_controller()->state());
434+}
435+
436+TEST(Provider, starting_updates_on_a_disabled_provider_does_nothing)
437+{
438+ using namespace ::testing;
439+
440+ NiceMock<MockProvider> p;
441+ EXPECT_CALL(p, start_position_updates()).Times(0);
442+ EXPECT_CALL(p, start_heading_updates()).Times(0);
443+ EXPECT_CALL(p, start_velocity_updates()).Times(0);
444+
445+ p.state_controller()->state() = cul::Provider::Controller::State::disabled;
446+
447+ p.state_controller()->start_position_updates();
448+ p.state_controller()->start_heading_updates();
449+ p.state_controller()->start_velocity_updates();
450+}
451+
452+TEST(Provider, disabling_a_provider_stops_all_updates)
453+{
454+ using namespace ::testing;
455+
456+ NiceMock<MockProvider> p;
457+ EXPECT_CALL(p, stop_position_updates()).Times(1);
458+ EXPECT_CALL(p, stop_heading_updates()).Times(1);
459+ EXPECT_CALL(p, stop_velocity_updates()).Times(1);
460+
461+ p.state_controller()->start_position_updates();
462+ p.state_controller()->start_heading_updates();
463+ p.state_controller()->start_velocity_updates();
464+
465+ p.state_controller()->state() = cul::Provider::Controller::State::disabled;
466+}
467+
468 #include <com/ubuntu/location/proxy_provider.h>
469
470 TEST(ProxyProvider, start_and_stop_of_updates_propagates_to_correct_providers)

Subscribers

People subscribed via source and target branches