Merge lp:~thomas-voss/location-service/expose-engine-state-information into lp:location-service/trunk

Proposed by Thomas Voß
Status: Merged
Approved by: Marcus Tomlinson
Approved revision: 249
Merged at revision: 252
Proposed branch: lp:~thomas-voss/location-service/expose-engine-state-information
Merge into: lp:location-service/trunk
Diff against target: 1022 lines (+597/-61)
19 files modified
include/location_service/com/ubuntu/location/codec.h (+45/-0)
include/location_service/com/ubuntu/location/service/interface.h (+24/-0)
include/location_service/com/ubuntu/location/service/skeleton.h (+8/-0)
include/location_service/com/ubuntu/location/service/state.h (+43/-0)
include/location_service/com/ubuntu/location/service/stub.h (+2/-0)
src/location_service/com/ubuntu/location/CMakeLists.txt (+2/-0)
src/location_service/com/ubuntu/location/engine.cpp (+19/-21)
src/location_service/com/ubuntu/location/engine.h (+4/-14)
src/location_service/com/ubuntu/location/service/daemon.cpp (+13/-0)
src/location_service/com/ubuntu/location/service/daemon.h (+3/-0)
src/location_service/com/ubuntu/location/service/implementation.cpp (+31/-6)
src/location_service/com/ubuntu/location/service/skeleton.cpp (+33/-0)
src/location_service/com/ubuntu/location/service/state.cpp (+71/-0)
src/location_service/com/ubuntu/location/service/stub.cpp (+7/-0)
src/location_service/com/ubuntu/location/state_tracking_provider.h (+162/-0)
tests/CMakeLists.txt (+1/-0)
tests/daemon_and_cli_tests.cpp (+10/-0)
tests/engine_test.cpp (+0/-20)
tests/state_tracking_provider_test.cpp (+119/-0)
To merge this branch: bzr merge lp:~thomas-voss/location-service/expose-engine-state-information
Reviewer Review Type Date Requested Status
Marcus Tomlinson (community) Approve
Scott Sweeny (community) Approve
PS Jenkins bot continuous-integration Pending
Review via email: mp+295336@code.launchpad.net

Commit message

Expose service::State to the bus.

Description of the change

Expose service::State to the bus.

To post a comment you must log in.
Revision history for this message
Scott Sweeny (ssweeny) wrote :

LGTM

review: Approve
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

The silo is currently failing due to a changeling mismatch in Yakkety (...-0ubuntu4 vs ...-0ubuntu1)

Failing that, I've built this branch here: https://launchpad.net/~unity-api-team/+archive/ubuntu/dev-build-1. However, once installed on the phone, apps that use location begin crashing.

To test, before installing this, make sure only the Apps scope is favourited (Otherwise, you'll end up with the dash stuck in a restart loop).

As soon as a scope that uses location is opened (such as Nearby or News), the dash crashes. Also, as soon as you hit the locate button in uNav, uNav crashes.

Oddly though, I've got nothing in /var/crash.

review: Needs Fixing
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

Hmmm, I seem to only get a PropertiesChanged signal for "State" when I disable location, no signal on enable, and no signal on active (afaict).

I'm running this on the phone:

dbus-monitor --system "interface='org.freedesktop.DBus.Properties',path=/com/ubuntu/location/Service"

I toggle the indicator switch on/off/on:

signal sender=:1.110 -> dest=(null destination) serial=559 path=/com/ubuntu/location/Service; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "com.ubuntu.location.Service"
   array [
      dict entry(
         string "IsOnline"
         variant boolean true
      )
   ]
   array [
   ]
signal sender=:1.110 -> dest=(null destination) serial=561 path=/com/ubuntu/location/Service; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "com.ubuntu.location.Service"
   array [
      dict entry(
         string "IsOnline"
         variant boolean false
      )
   ]
   array [
   ]
signal sender=:1.110 -> dest=(null destination) serial=562 path=/com/ubuntu/location/Service; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "com.ubuntu.location.Service"
   array [
      dict entry(
         string "State"
         variant string "disabled"
      )
   ]
   array [
   ]
signal sender=:1.110 -> dest=(null destination) serial=564 path=/com/ubuntu/location/Service; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "com.ubuntu.location.Service"
   array [
      dict entry(
         string "IsOnline"
         variant boolean true
      )
   ]
   array [
   ]

review: Needs Fixing
248. By Thomas Voß

Fix copy'n'paste leftover.

Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

Just to recap where we are now: Your last change indeed fixed the "enabled" / "disabled" properties changes, thanks! We can at least rest assured that these signals will propagate through to the indicator. However, we now face an issue where we don't ever get an "active" status (even when it is clear that our position is being tracked).

review: Needs Fixing
249. By Thomas Voß

Introduce a StateTrackingProvider enabling the engine to track enabled/active state.

Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

This really is looking good now, thanks!

So one last concern is the silo's current build status: "Failed to build (location-service/vivid, location-service/yakkety)."

A few builds are failing, not sure which are expected: https://launchpad.net/~ci-train-ppa-service/+archive/ubuntu/landing-049/+packages

review: Needs Fixing
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

Awesome, Good to go here. Thanks Thomas!

review: Approve

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/codec.h'
2--- include/location_service/com/ubuntu/location/codec.h 2014-09-12 15:04:21 +0000
3+++ include/location_service/com/ubuntu/location/codec.h 2016-06-11 19:59:38 +0000
4@@ -25,6 +25,7 @@
5 #include <com/ubuntu/location/space_vehicle.h>
6 #include <com/ubuntu/location/update.h>
7 #include <com/ubuntu/location/velocity.h>
8+#include <com/ubuntu/location/service/state.h>
9 #include <com/ubuntu/location/units/units.h>
10 #include <com/ubuntu/location/wgs84/altitude.h>
11 #include <com/ubuntu/location/wgs84/latitude.h>
12@@ -32,12 +33,56 @@
13
14 #include <core/dbus/codec.h>
15
16+#include <sstream>
17+
18 namespace core
19 {
20 namespace dbus
21 {
22 namespace helper
23 {
24+template<>
25+struct TypeMapper<com::ubuntu::location::service::State>
26+{
27+ constexpr static ArgumentType type_value()
28+ {
29+ return ArgumentType::string;
30+ }
31+
32+ constexpr static bool is_basic_type()
33+ {
34+ return true;
35+ }
36+ constexpr static bool requires_signature()
37+ {
38+ return false;
39+ }
40+
41+ static std::string signature()
42+ {
43+ static const std::string s = TypeMapper<std::string>::signature();
44+ return s;
45+ }
46+};
47+}
48+
49+template<>
50+struct Codec<com::ubuntu::location::service::State>
51+{
52+ static void encode_argument(Message::Writer& writer, const com::ubuntu::location::service::State& in)
53+ {
54+ std::stringstream ss; ss << in; auto s = ss.str();
55+ writer.push_stringn(s.c_str(), s.size());
56+ }
57+
58+ static void decode_argument(Message::Reader& reader, com::ubuntu::location::service::State& in)
59+ {
60+ auto s = reader.pop_string();
61+ std::stringstream ss{s}; ss >> in;
62+ }
63+};
64+namespace helper
65+{
66 template<typename T>
67 struct TypeMapper<com::ubuntu::location::units::Quantity<T>>
68 {
69
70=== modified file 'include/location_service/com/ubuntu/location/service/interface.h'
71--- include/location_service/com/ubuntu/location/service/interface.h 2014-08-01 15:59:25 +0000
72+++ include/location_service/com/ubuntu/location/service/interface.h 2016-06-11 19:59:38 +0000
73@@ -18,6 +18,7 @@
74 #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_INTERFACE_H_
75 #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_INTERFACE_H_
76
77+#include <com/ubuntu/location/service/state.h>
78 #include <com/ubuntu/location/service/session/interface.h>
79
80 #include <com/ubuntu/location/space_vehicle.h>
81@@ -87,6 +88,23 @@
82
83 struct Properties
84 {
85+ struct State
86+ {
87+ inline static const std::string& name()
88+ {
89+ static const std::string s
90+ {
91+ "State"
92+ };
93+ return s;
94+ }
95+
96+ typedef com::ubuntu::location::service::Interface Interface;
97+ typedef com::ubuntu::location::service::State ValueType;
98+ static const bool readable = true;
99+ static const bool writable = true;
100+ };
101+
102 struct DoesSatelliteBasedPositioning
103 {
104 inline static const std::string& name()
105@@ -176,6 +194,12 @@
106 virtual ~Interface() = default;
107
108 /**
109+ * @brief The overall state of the service.
110+ * @return a getable/observable property.
111+ */
112+ virtual const core::Property<State>& state() const = 0;
113+
114+ /**
115 * @brief Whether the service uses satellite-based positioning.
116 * @return A setable/getable/observable property.
117 */
118
119=== modified file 'include/location_service/com/ubuntu/location/service/skeleton.h'
120--- include/location_service/com/ubuntu/location/service/skeleton.h 2015-02-13 13:19:18 +0000
121+++ include/location_service/com/ubuntu/location/service/skeleton.h 2016-06-11 19:59:38 +0000
122@@ -111,11 +111,15 @@
123 ~Skeleton() noexcept;
124
125 // From com::ubuntu::location::service::Interface
126+ const core::Property<State>& state() const;
127 core::Property<bool>& does_satellite_based_positioning();
128 core::Property<bool>& does_report_cell_and_wifi_ids();
129 core::Property<bool>& is_online();
130 core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles();
131
132+protected:
133+ // Enable subclasses to alter the state.
134+ core::Property<State>& mutable_state();
135 private:
136 // Handles incoming message calls for create_session_for_criteria.
137 // Dispatches to the actual implementation, and manages object lifetimes.
138@@ -131,6 +135,8 @@
139 // Removes the session with the given path from the session store.
140 void remove_from_session_store_for_path(const core::dbus::types::ObjectPath& path);
141
142+ // Called whenever the overall state of the service changes.
143+ void on_state_changed(State state);
144 // Called whenever the value of the respective property changes.
145 void on_does_satellite_based_positioning_changed(bool value);
146 // Called whenever the value of the respective property changes.
147@@ -154,6 +160,7 @@
148 // DBus properties as exposed on the bus for com.ubuntu.location.service.Interface
149 struct
150 {
151+ std::shared_ptr< core::dbus::Property<Interface::Properties::State> > state;
152 std::shared_ptr< core::dbus::Property<Interface::Properties::DoesSatelliteBasedPositioning> > does_satellite_based_positioning;
153 std::shared_ptr< core::dbus::Property<Interface::Properties::DoesReportCellAndWifiIds> > does_report_cell_and_wifi_ids;
154 std::shared_ptr< core::dbus::Property<Interface::Properties::IsOnline> > is_online;
155@@ -162,6 +169,7 @@
156 // We sign up to property changes here, to be able to report them to the bus
157 struct
158 {
159+ core::ScopedConnection state;
160 core::ScopedConnection does_satellite_based_positioning;
161 core::ScopedConnection does_report_cell_and_wifi_ids;
162 core::ScopedConnection is_online;
163
164=== added file 'include/location_service/com/ubuntu/location/service/state.h'
165--- include/location_service/com/ubuntu/location/service/state.h 1970-01-01 00:00:00 +0000
166+++ include/location_service/com/ubuntu/location/service/state.h 2016-06-11 19:59:38 +0000
167@@ -0,0 +1,43 @@
168+/*
169+ * Copyright © 2016 Canonical Ltd.
170+ *
171+ * This program is free software: you can redistribute it and/or modify it
172+ * under the terms of the GNU Lesser General Public License version 3,
173+ * as published by the Free Software Foundation.
174+ *
175+ * This program is distributed in the hope that it will be useful,
176+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
177+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
178+ * GNU Lesser General Public License for more details.
179+ *
180+ * You should have received a copy of the GNU Lesser General Public License
181+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
182+ *
183+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
184+ */
185+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_STATE_H_
186+#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_STATE_H_
187+
188+#include <iosfwd>
189+
190+namespace com { namespace ubuntu { namespace location { namespace service
191+{
192+/// @brief State enumerates the known states of the service.
193+enum class State
194+{
195+ disabled, ///< The service has been disabled by the user.
196+ enabled, ///< The service is enabled but not actively carrying out positioning.
197+ active ///< The service is actively trying to determine the position of the device.
198+};
199+
200+/// @brief operator== returns true if lhs == rhs.
201+bool operator==(State lhs, State rhs);
202+/// @brief operator != returns true if !(lhs == rhs).
203+bool operator!=(State lhs, State rhs);
204+
205+/// @brief operator<< inserts state into the out.
206+std::ostream& operator<<(std::ostream& out, State state);
207+/// @brief operator>> extracts state from in.
208+std::istream& operator>>(std::istream& in, State& state);
209+}}}}
210+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_STATE_H_
211
212=== modified file 'include/location_service/com/ubuntu/location/service/stub.h'
213--- include/location_service/com/ubuntu/location/service/stub.h 2014-02-03 13:52:21 +0000
214+++ include/location_service/com/ubuntu/location/service/stub.h 2016-06-11 19:59:38 +0000
215@@ -40,6 +40,8 @@
216 ~Stub() noexcept;
217
218 session::Interface::Ptr create_session_for_criteria(const Criteria& criteria);
219+
220+ const core::Property<State>& state() const;
221 core::Property<bool>& does_satellite_based_positioning();
222 core::Property<bool>& does_report_cell_and_wifi_ids();
223 core::Property<bool>& is_online();
224
225=== modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt'
226--- src/location_service/com/ubuntu/location/CMakeLists.txt 2016-04-05 21:26:06 +0000
227+++ src/location_service/com/ubuntu/location/CMakeLists.txt 2016-06-11 19:59:38 +0000
228@@ -35,6 +35,7 @@
229 proxy_provider.cpp
230 satellite_based_positioning_state.cpp
231 settings.cpp
232+ state_tracking_provider.h
233 time_based_update_policy.cpp
234 set_name_for_thread.cpp
235 time_since_boot.cpp
236@@ -50,6 +51,7 @@
237 service/runtime.cpp
238 service/runtime_tests.h
239 service/runtime_tests.cpp
240+ service/state.cpp
241 service/trust_store_permission_manager.cpp
242
243 service/implementation.cpp
244
245=== modified file 'src/location_service/com/ubuntu/location/engine.cpp'
246--- src/location_service/com/ubuntu/location/engine.cpp 2016-03-02 14:23:41 +0000
247+++ src/location_service/com/ubuntu/location/engine.cpp 2016-06-11 19:59:38 +0000
248@@ -19,6 +19,7 @@
249
250 #include <com/ubuntu/location/logging.h>
251 #include <com/ubuntu/location/provider_selection_policy.h>
252+#include <com/ubuntu/location/state_tracking_provider.h>
253
254 #include <iostream>
255 #include <stdexcept>
256@@ -138,16 +139,13 @@
257 return provider_selection_policy->determine_provider_selection_for_criteria(criteria, *this);
258 }
259
260-bool cul::Engine::has_provider(const cul::Provider::Ptr& provider) noexcept
261-{
262- return providers.count(provider) > 0;
263-}
264-
265-void cul::Engine::add_provider(const cul::Provider::Ptr& provider)
266-{
267- if (!provider)
268+void cul::Engine::add_provider(const cul::Provider::Ptr& impl)
269+{
270+ if (!impl)
271 throw std::runtime_error("Cannot add null provider");
272
273+ auto provider = std::make_shared<StateTrackingProvider>(impl);
274+
275 // We synchronize to the engine state.
276 if (provider->requires(Provider::Requirements::satellites) && configuration.satellite_based_positioning_state == SatelliteBasedPositioningState::off)
277 provider->state_controller()->disable();
278@@ -207,24 +205,24 @@
279 updates.last_known_location = update_policy->verify_update(src);
280 });
281
282- std::lock_guard<std::mutex> lg(guard);
283- providers.emplace(provider, std::move(ProviderConnections{cp, ch, cv, cr, cs, cpr}));
284-}
285-
286-void cul::Engine::remove_provider(const cul::Provider::Ptr& provider) noexcept
287-{
288- std::lock_guard<std::mutex> lg(guard);
289-
290- auto it = providers.find(provider);
291- if (it != providers.end())
292+ auto cps = provider->state().changed().connect([this](const StateTrackingProvider::State&)
293 {
294- providers.erase(it);
295- }
296+ bool is_any_active = false;
297+
298+ std::lock_guard<std::recursive_mutex> lg(guard);
299+ for (const auto& pair : providers)
300+ is_any_active = pair.first->state() == StateTrackingProvider::State::active;
301+
302+ configuration.engine_state = is_any_active ? Engine::Status::active : Engine::Status::on;
303+ });
304+
305+ std::lock_guard<std::recursive_mutex> lg(guard);
306+ providers.emplace(provider, std::move(ProviderConnections{cp, ch, cv, cr, cs, cpr, cps}));
307 }
308
309 void cul::Engine::for_each_provider(const std::function<void(const Provider::Ptr&)>& enumerator) const noexcept
310 {
311- std::lock_guard<std::mutex> lg(guard);
312+ std::lock_guard<std::recursive_mutex> lg(guard);
313 for (const auto& provider : providers)
314 {
315 try
316
317=== modified file 'src/location_service/com/ubuntu/location/engine.h'
318--- src/location_service/com/ubuntu/location/engine.h 2015-11-19 09:55:37 +0000
319+++ src/location_service/com/ubuntu/location/engine.h 2016-06-11 19:59:38 +0000
320@@ -24,6 +24,7 @@
321 #include <com/ubuntu/location/provider_selection_policy.h>
322 #include <com/ubuntu/location/satellite_based_positioning_state.h>
323 #include <com/ubuntu/location/space_vehicle.h>
324+#include <com/ubuntu/location/state_tracking_provider.h>
325 #include <com/ubuntu/location/wifi_and_cell_reporting_state.h>
326
327 #include <com/ubuntu/location/settings.h>
328@@ -151,24 +152,12 @@
329 virtual ProviderSelection determine_provider_selection_for_criteria(const Criteria& criteria);
330
331 /**
332- * @brief Checks if the engine knows about a specific provider.
333- * @return True iff the engine knows about the provider.
334- */
335- virtual bool has_provider(const Provider::Ptr& provider) noexcept;
336-
337- /**
338 * @brief Makes a provider known to the engine.
339 * @param provider The new provider.
340 */
341 virtual void add_provider(const Provider::Ptr& provider);
342
343 /**
344- * @brief Removes a provider from the engine.
345- * @param provider The provider to be removed.
346- */
347- virtual void remove_provider(const Provider::Ptr& provider) noexcept;
348-
349- /**
350 * @brief Iterates all known providers and invokes the provided enumerator for each of them.
351 * @param enumerator The functor to be invoked for each provider.
352 */
353@@ -189,10 +178,11 @@
354 core::ScopedConnection wifi_and_cell_id_reporting_state_updates;
355 core::ScopedConnection space_vehicle_visibility_updates;
356 core::ScopedConnection provider_position_updates;
357+ core::ScopedConnection provider_state_updates;
358 };
359
360- mutable std::mutex guard;
361- std::map<Provider::Ptr, ProviderConnections> providers;
362+ mutable std::recursive_mutex guard;
363+ std::map<StateTrackingProvider::Ptr, ProviderConnections> providers;
364 ProviderSelectionPolicy::Ptr provider_selection_policy;
365 Settings::Ptr settings;
366 UpdatePolicy::Ptr update_policy;
367
368=== modified file 'src/location_service/com/ubuntu/location/service/daemon.cpp'
369--- src/location_service/com/ubuntu/location/service/daemon.cpp 2016-03-31 20:31:05 +0000
370+++ src/location_service/com/ubuntu/location/service/daemon.cpp 2016-06-11 19:59:38 +0000
371@@ -265,6 +265,7 @@
372 options.add("help", "Produces this help message");
373 options.add("property",
374 "Property to set/get from a running service, known properties are:\n"
375+ " state [get]\n"
376 " is_online [get/set]\n"
377 " does_satellite_based_positioning [get/set]\n"
378 " does_report_wifi_and_cell_ids [get/set]\n"
379@@ -346,6 +347,15 @@
380
381 switch (config.property)
382 {
383+ case Property::state:
384+ switch (config.command)
385+ {
386+ case Command::get:
387+ std::cout << "Location service is " << location_service->state() << std::endl;
388+ break;
389+ default:
390+ break;
391+ }
392 case Property::is_online:
393 switch (config.command)
394 {
395@@ -468,6 +478,7 @@
396 {
397 static const std::map<std::string, location::service::Daemon::Cli::Property> lut =
398 {
399+ {"state", location::service::Daemon::Cli::Property::state},
400 {"is_online", location::service::Daemon::Cli::Property::is_online},
401 {"does_satellite_based_positioning", location::service::Daemon::Cli::Property::does_satellite_based_positioning},
402 {"does_report_wifi_and_cell_ids", location::service::Daemon::Cli::Property::does_report_wifi_and_cell_ids},
403@@ -492,6 +503,8 @@
404 {
405 switch (property)
406 {
407+ case location::service::Daemon::Cli::Property::state:
408+ out << "state"; break;
409 case location::service::Daemon::Cli::Property::is_online:
410 out << "is_online"; break;
411 case location::service::Daemon::Cli::Property::does_satellite_based_positioning:
412
413=== modified file 'src/location_service/com/ubuntu/location/service/daemon.h'
414--- src/location_service/com/ubuntu/location/service/daemon.h 2016-01-11 15:20:19 +0000
415+++ src/location_service/com/ubuntu/location/service/daemon.h 2016-06-11 19:59:38 +0000
416@@ -63,6 +63,8 @@
417 {
418 /** @brief Marks the unknown property. */
419 unknown,
420+ /** @brief State describes the overall state of the service. */
421+ state,
422 /** @brief Indicates whether the positioning engine is online. */
423 is_online,
424 /** @brief Indicates whether the positioning engine uses satellite-based positioning. */
425@@ -82,6 +84,7 @@
426 * --help Produces this help message
427 * --property arg (=unknown) Property to set/get from a running service, known
428 properties are:
429+ state [get]
430 is_online [get/set]
431 does_satellite_based_positioning [get/set]
432 does_report_wifi_and_cell_ids [get/set]
433
434=== modified file 'src/location_service/com/ubuntu/location/service/implementation.cpp'
435--- src/location_service/com/ubuntu/location/service/implementation.cpp 2015-12-09 15:18:14 +0000
436+++ src/location_service/com/ubuntu/location/service/implementation.cpp 2016-06-11 19:59:38 +0000
437@@ -98,9 +98,21 @@
438 configuration.engine->configuration.engine_state.changed().connect(
439 [this](Engine::Status status)
440 {
441- is_online() =
442- status == Engine::Status::on ||
443- status == Engine::Status::active;
444+ switch (status)
445+ {
446+ case Engine::Status::off:
447+ is_online() = false;
448+ mutable_state() = State::disabled;
449+ break;
450+ case Engine::Status::on:
451+ is_online() = true;
452+ mutable_state() = State::enabled;
453+ break;
454+ case Engine::Status::active:
455+ is_online() = true;
456+ mutable_state() = State::active;
457+ break;
458+ }
459 }),
460 configuration.engine->configuration.satellite_based_positioning_state.changed().connect(
461 [this](cul::SatelliteBasedPositioningState state)
462@@ -132,9 +144,22 @@
463 if (!configuration.permission_manager)
464 throw std::runtime_error("Cannot create service for null permission manager.");
465
466- is_online() =
467- configuration.engine->configuration.engine_state == Engine::Status::on ||
468- configuration.engine->configuration.engine_state == Engine::Status::active;
469+ switch (configuration.engine->configuration.engine_state)
470+ {
471+ case Engine::Status::off:
472+ is_online() = false;
473+ mutable_state() = State::disabled;
474+ break;
475+ case Engine::Status::on:
476+ is_online() = true;
477+ mutable_state() = State::enabled;
478+ break;
479+ case Engine::Status::active:
480+ is_online() = true;
481+ mutable_state() = State::active;
482+ break;
483+ };
484+
485 does_report_cell_and_wifi_ids() =
486 configuration.engine->configuration.wifi_and_cell_id_reporting_state ==
487 cul::WifiAndCellIdReportingState::on;
488
489=== modified file 'src/location_service/com/ubuntu/location/service/skeleton.cpp'
490--- src/location_service/com/ubuntu/location/service/skeleton.cpp 2015-02-13 13:19:18 +0000
491+++ src/location_service/com/ubuntu/location/service/skeleton.cpp 2016-06-11 19:59:38 +0000
492@@ -73,6 +73,7 @@
493 properties_changed(object->get_signal<core::dbus::interfaces::Properties::Signals::PropertiesChanged>()),
494 properties
495 {
496+ object->get_property<culs::Interface::Properties::State>(),
497 object->get_property<culs::Interface::Properties::DoesSatelliteBasedPositioning>(),
498 object->get_property<culs::Interface::Properties::DoesReportCellAndWifiIds>(),
499 object->get_property<culs::Interface::Properties::IsOnline>(),
500@@ -80,6 +81,10 @@
501 },
502 connections
503 {
504+ properties.state->changed().connect([this](State state)
505+ {
506+ on_state_changed(state);
507+ }),
508 properties.does_satellite_based_positioning->changed().connect([this](bool value)
509 {
510 on_does_satellite_based_positioning_changed(value);
511@@ -105,6 +110,11 @@
512 object->uninstall_method_handler<culs::Interface::CreateSessionForCriteria>();
513 }
514
515+core::Property<culs::State>& culs::Skeleton::mutable_state()
516+{
517+ return *properties.state;
518+}
519+
520 void culs::Skeleton::handle_create_session_for_criteria(const dbus::Message::Ptr& in)
521 {
522 VLOG(1) << __PRETTY_FUNCTION__;
523@@ -208,6 +218,24 @@
524 session_store.erase(path);
525 }
526
527+void culs::Skeleton::on_state_changed(culs::State state)
528+{
529+ std::map<std::string, core::dbus::types::Variant> dict
530+ {
531+ {
532+ culs::Interface::Properties::State::name(),
533+ core::dbus::types::Variant::encode(state)
534+ }
535+ };
536+
537+ properties_changed->emit(
538+ std::tie(
539+ core::dbus::traits::Service<culs::Interface>::interface_name(),
540+ dict,
541+ the_empty_array_of_invalidated_properties()));
542+}
543+
544+
545 void culs::Skeleton::on_does_satellite_based_positioning_changed(bool value)
546 {
547 std::map<std::string, core::dbus::types::Variant> dict
548@@ -258,6 +286,11 @@
549 the_empty_array_of_invalidated_properties()));
550 }
551
552+const core::Property<culs::State>& culs::Skeleton::state() const
553+{
554+ return *properties.state;
555+}
556+
557 core::Property<bool>& culs::Skeleton::does_satellite_based_positioning()
558 {
559 return *properties.does_satellite_based_positioning;
560
561=== added file 'src/location_service/com/ubuntu/location/service/state.cpp'
562--- src/location_service/com/ubuntu/location/service/state.cpp 1970-01-01 00:00:00 +0000
563+++ src/location_service/com/ubuntu/location/service/state.cpp 2016-06-11 19:59:38 +0000
564@@ -0,0 +1,71 @@
565+/*
566+ * Copyright © 2016 Canonical Ltd.
567+ *
568+ * This program is free software: you can redistribute it and/or modify it
569+ * under the terms of the GNU Lesser General Public License version 3,
570+ * as published by the Free Software Foundation.
571+ *
572+ * This program is distributed in the hope that it will be useful,
573+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
574+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
575+ * GNU Lesser General Public License for more details.
576+ *
577+ * You should have received a copy of the GNU Lesser General Public License
578+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
579+ *
580+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
581+ */
582+
583+#include <com/ubuntu/location/service/state.h>
584+
585+#include <map>
586+#include <type_traits>
587+
588+namespace culs = com::ubuntu::location::service;
589+
590+namespace
591+{
592+typedef typename std::underlying_type<culs::State>::type UT;
593+
594+typedef std::pair<std::map<culs::State, std::string>, std::map<std::string, culs::State>> Lut;
595+
596+const Lut& lut()
597+{
598+ static const Lut instance
599+ {
600+ {
601+ {culs::State::disabled, "disabled"},
602+ {culs::State::enabled, "enabled"},
603+ {culs::State::active, "active"}
604+ },
605+ {
606+ {"disabled", culs::State::disabled},
607+ {"enabled", culs::State::enabled},
608+ {"active", culs::State::active}
609+ }
610+ };
611+
612+ return instance;
613+}
614+}
615+
616+bool culs::operator==(culs::State lhs, culs::State rhs)
617+{
618+ return static_cast<UT>(lhs) == static_cast<UT>(rhs);
619+}
620+
621+bool culs::operator!=(culs::State lhs, culs::State rhs)
622+{
623+ return static_cast<UT>(lhs) != static_cast<UT>(rhs);
624+}
625+
626+std::ostream& culs::operator<<(std::ostream& out, culs::State state)
627+{
628+ return out << lut().first.at(state);
629+}
630+
631+std::istream& culs::operator>>(std::istream& in, culs::State& state)
632+{
633+ std::string s; in >> s; state = lut().second.at(s);
634+ return in;
635+}
636
637=== modified file 'src/location_service/com/ubuntu/location/service/stub.cpp'
638--- src/location_service/com/ubuntu/location/service/stub.cpp 2014-07-17 14:03:42 +0000
639+++ src/location_service/com/ubuntu/location/service/stub.cpp 2016-06-11 19:59:38 +0000
640@@ -34,6 +34,7 @@
641 const dbus::Object::Ptr& object)
642 : bus(connection),
643 object(object),
644+ state(object->get_property<culs::Interface::Properties::State>()),
645 does_satellite_based_positioning(object->get_property<culs::Interface::Properties::DoesSatelliteBasedPositioning>()),
646 does_report_cell_and_wifi_ids(object->get_property<culs::Interface::Properties::DoesReportCellAndWifiIds>()),
647 is_online(object->get_property<culs::Interface::Properties::IsOnline>()),
648@@ -43,6 +44,7 @@
649
650 dbus::Bus::Ptr bus;
651 dbus::Object::Ptr object;
652+ std::shared_ptr<dbus::Property<culs::Interface::Properties::State>> state;
653 std::shared_ptr<dbus::Property<culs::Interface::Properties::DoesSatelliteBasedPositioning>> does_satellite_based_positioning;
654 std::shared_ptr<dbus::Property<culs::Interface::Properties::DoesReportCellAndWifiIds>> does_report_cell_and_wifi_ids;
655 std::shared_ptr<dbus::Property<culs::Interface::Properties::IsOnline>> is_online;
656@@ -74,6 +76,11 @@
657 return culss::Interface::Ptr(new culss::Stub{d->bus, op.value()});
658 }
659
660+const core::Property<culs::State>& culs::Stub::state() const
661+{
662+ return *d->state;
663+}
664+
665 core::Property<bool>& culs::Stub::does_satellite_based_positioning()
666 {
667 return *d->does_satellite_based_positioning;
668
669=== added file 'src/location_service/com/ubuntu/location/state_tracking_provider.h'
670--- src/location_service/com/ubuntu/location/state_tracking_provider.h 1970-01-01 00:00:00 +0000
671+++ src/location_service/com/ubuntu/location/state_tracking_provider.h 2016-06-11 19:59:38 +0000
672@@ -0,0 +1,162 @@
673+/*
674+ * Copyright © 2016 Canonical Ltd.
675+ *
676+ * This program is free software: you can redistribute it and/or modify it
677+ * under the terms of the GNU Lesser General Public License version 3,
678+ * as published by the Free Software Foundation.
679+ *
680+ * This program is distributed in the hope that it will be useful,
681+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
682+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
683+ * GNU Lesser General Public License for more details.
684+ *
685+ * You should have received a copy of the GNU Lesser General Public License
686+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
687+ *
688+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
689+ */
690+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_STATE_TRACKING_PROVIDER_H_
691+#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_STATE_TRACKING_PROVIDER_H_
692+
693+#include <com/ubuntu/location/provider.h>
694+
695+#include <memory>
696+
697+namespace com
698+{
699+namespace ubuntu
700+{
701+namespace location
702+{
703+// StateTrackingProvider keeps track of the State of an individual provider instance.
704+//
705+// TODO(tvoss): Factor this functionality into the public interface once we find time
706+// to break API/ABI of providers.
707+class StateTrackingProvider : public Provider
708+{
709+public:
710+ // Safe us some typing
711+ typedef std::shared_ptr<StateTrackingProvider> Ptr;
712+
713+ // State models the different states of a provider.
714+ enum class State
715+ {
716+ active, // The provider is actively delivering updates.
717+ enabled // The provider is enabled but not actively delivering updates.
718+ };
719+
720+ StateTrackingProvider(const Provider::Ptr& impl)
721+ : impl_{impl},
722+ connections
723+ {
724+ impl_->updates().position.connect(
725+ [this](const Update<Position>& u)
726+ {
727+ mutable_updates().position(u);
728+ }),
729+ impl_->updates().heading.connect(
730+ [this](const Update<Heading>& u)
731+ {
732+ mutable_updates().heading(u);
733+ }),
734+ impl_->updates().velocity.connect(
735+ [this](const Update<Velocity>& u)
736+ {
737+ mutable_updates().velocity(u);
738+ })
739+ },
740+ state_{State::enabled}
741+ {
742+ }
743+
744+ const core::Property<State>& state() const
745+ {
746+ return state_;
747+ }
748+
749+ bool supports(const Features& f) const override
750+ {
751+ return impl_->supports(f);
752+ }
753+
754+ bool requires(const Requirements& r) const override
755+ {
756+ return impl_->requires(r);
757+ }
758+
759+ bool matches_criteria(const Criteria& criteria) override
760+ {
761+ return impl_->matches_criteria(criteria);
762+ }
763+
764+ void on_wifi_and_cell_reporting_state_changed(WifiAndCellIdReportingState state) override
765+ {
766+ impl_->on_wifi_and_cell_reporting_state_changed(state);
767+ }
768+
769+ void on_reference_location_updated(const Update<Position>& position) override
770+ {
771+ impl_->on_reference_location_updated(position);
772+ }
773+
774+ void on_reference_velocity_updated(const Update<Velocity>& velocity) override
775+ {
776+ impl_->on_reference_velocity_updated(velocity);
777+ }
778+
779+ void on_reference_heading_updated(const Update<Heading>& heading) override
780+ {
781+ impl_->on_reference_heading_updated(heading);
782+ }
783+
784+ void start_position_updates() override
785+ {
786+ state_ = State::active;
787+ impl_->state_controller()->start_position_updates();
788+ }
789+
790+ void stop_position_updates() override
791+ {
792+ state_ = State::enabled;
793+ impl_->state_controller()->stop_position_updates();
794+ }
795+
796+ void start_velocity_updates() override
797+ {
798+ state_ = State::active;
799+ impl_->state_controller()->start_velocity_updates();
800+ }
801+
802+ void stop_velocity_updates() override
803+ {
804+ state_ = State::enabled;
805+ impl_->state_controller()->stop_velocity_updates();
806+ }
807+
808+ void start_heading_updates() override
809+ {
810+ state_ = State::active;
811+ impl_->state_controller()->start_heading_updates();
812+ }
813+
814+ void stop_heading_updates() override
815+ {
816+ state_ = State::enabled;
817+ impl_->state_controller()->stop_heading_updates();
818+ }
819+
820+private:
821+ Provider::Ptr impl_;
822+ struct
823+ {
824+ core::ScopedConnection position_updates;
825+ core::ScopedConnection heading_updates;
826+ core::ScopedConnection velocity_updates;
827+ } connections;
828+ core::Property<State> state_;
829+};
830+}
831+}
832+}
833+
834+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_STATE_TRACKING_PROVIDER_H_
835
836=== modified file 'tests/CMakeLists.txt'
837--- tests/CMakeLists.txt 2016-03-31 10:15:53 +0000
838+++ tests/CMakeLists.txt 2016-06-11 19:59:38 +0000
839@@ -93,6 +93,7 @@
840 LOCATION_SERVICE_ADD_TEST(wgs84_test wgs84_test.cpp)
841 LOCATION_SERVICE_ADD_TEST(trust_store_permission_manager_test trust_store_permission_manager_test.cpp)
842 LOCATION_SERVICE_ADD_TEST(runtime_test runtime_test.cpp)
843+LOCATION_SERVICE_ADD_TEST(state_tracking_provider_test state_tracking_provider_test.cpp)
844
845 # Provider-specific test-cases go here.
846 if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
847
848=== modified file 'tests/daemon_and_cli_tests.cpp'
849--- tests/daemon_and_cli_tests.cpp 2016-01-28 20:16:11 +0000
850+++ tests/daemon_and_cli_tests.cpp 2016-06-11 19:59:38 +0000
851@@ -122,6 +122,16 @@
852 }
853 }
854
855+TEST_F(DaemonAndCli, QueryingStatePropertyWorks)
856+{
857+ EXPECT_EQ(core::testing::ForkAndRunResult::empty,
858+ core::testing::fork_and_run(
859+ testing_daemon(*this),
860+ querying_cli_for_property(
861+ location::service::Daemon::Cli::Property::state,
862+ *this)));
863+}
864+
865 TEST_F(DaemonAndCli, QueryingIsOnlinePropertyWorks)
866 {
867 EXPECT_EQ(core::testing::ForkAndRunResult::empty,
868
869=== modified file 'tests/engine_test.cpp'
870--- tests/engine_test.cpp 2016-03-02 15:26:21 +0000
871+++ tests/engine_test.cpp 2016-06-11 19:59:38 +0000
872@@ -72,26 +72,6 @@
873 }
874 }
875
876-TEST(Engine, adding_and_removing_providers_inserts_and_erases_from_underlying_collection)
877-{
878- location::Engine engine {std::make_shared<NullProviderSelectionPolicy>(), mock_settings()};
879-
880- auto provider1 = std::make_shared<testing::NiceMock<MockProvider>>();
881- auto provider2 = std::make_shared<testing::NiceMock<MockProvider>>();
882-
883- engine.add_provider(provider1);
884- EXPECT_TRUE(engine.has_provider(provider1));
885-
886- engine.add_provider(provider2);
887- EXPECT_TRUE(engine.has_provider(provider2));
888-
889- engine.remove_provider(provider1);
890- EXPECT_FALSE(engine.has_provider(provider1));
891-
892- engine.remove_provider(provider2);
893- EXPECT_FALSE(engine.has_provider(provider2));
894-}
895-
896 TEST(Engine, adding_a_null_provider_throws)
897 {
898 location::Engine engine {std::make_shared<NullProviderSelectionPolicy>(), mock_settings()};
899
900=== added file 'tests/state_tracking_provider_test.cpp'
901--- tests/state_tracking_provider_test.cpp 1970-01-01 00:00:00 +0000
902+++ tests/state_tracking_provider_test.cpp 2016-06-11 19:59:38 +0000
903@@ -0,0 +1,119 @@
904+/*
905+ * Copyright © 2016 Canonical Ltd.
906+ *
907+ * This program is free software: you can redistribute it and/or modify it
908+ * under the terms of the GNU Lesser General Public License version 3,
909+ * as published by the Free Software Foundation.
910+ *
911+ * This program is distributed in the hope that it will be useful,
912+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
913+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
914+ * GNU Lesser General Public License for more details.
915+ *
916+ * You should have received a copy of the GNU Lesser General Public License
917+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
918+ *
919+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
920+ */
921+
922+#include <com/ubuntu/location/state_tracking_provider.h>
923+
924+#include <com/ubuntu/location/clock.h>
925+#include <com/ubuntu/location/update.h>
926+#include <com/ubuntu/location/position.h>
927+#include <com/ubuntu/location/units/units.h>
928+#include <com/ubuntu/location/wgs84/latitude.h>
929+#include <com/ubuntu/location/wgs84/longitude.h>
930+#include <com/ubuntu/location/wgs84/altitude.h>
931+
932+#include "mock_provider.h"
933+
934+#include <gtest/gtest.h>
935+
936+namespace cul = com::ubuntu::location;
937+
938+namespace
939+{
940+auto timestamp = cul::Clock::now();
941+
942+// Create reference objects for injecting and validating updates.
943+cul::Update<cul::Position> reference_position_update
944+{
945+ {
946+ cul::wgs84::Latitude{9. * cul::units::Degrees},
947+ cul::wgs84::Longitude{53. * cul::units::Degrees},
948+ cul::wgs84::Altitude{-2. * cul::units::Meters}
949+ },
950+ timestamp
951+};
952+
953+cul::Update<cul::Velocity> reference_velocity_update
954+{
955+ {5. * cul::units::MetersPerSecond},
956+ timestamp
957+};
958+
959+cul::Update<cul::Heading> reference_heading_update
960+{
961+ {120. * cul::units::Degrees},
962+ timestamp
963+};
964+}
965+TEST(StateTrackingProviderTest, forwards_calls_to_impl)
966+{
967+ using namespace testing;
968+
969+ auto impl = std::make_shared<MockProvider>();
970+ EXPECT_CALL(*impl, supports(_)).Times(1).WillOnce(Return(true));
971+ EXPECT_CALL(*impl, requires(_)).Times(1).WillOnce(Return(false));
972+ EXPECT_CALL(*impl, matches_criteria(_)).Times(1).WillOnce(Return(false));
973+ EXPECT_CALL(*impl, on_wifi_and_cell_reporting_state_changed(_)).Times(1);
974+ EXPECT_CALL(*impl, on_reference_location_updated(_)).Times(1);
975+ EXPECT_CALL(*impl, on_reference_velocity_updated(_)).Times(1);
976+ EXPECT_CALL(*impl, on_reference_heading_updated(_)).Times(1);
977+ EXPECT_CALL(*impl, start_position_updates()).Times(1);
978+ EXPECT_CALL(*impl, stop_position_updates()).Times(1);
979+ EXPECT_CALL(*impl, start_velocity_updates()).Times(1);
980+ EXPECT_CALL(*impl, stop_velocity_updates()).Times(1);
981+ EXPECT_CALL(*impl, start_heading_updates()).Times(1);
982+ EXPECT_CALL(*impl, stop_heading_updates()).Times(1);
983+
984+ com::ubuntu::location::StateTrackingProvider stp{impl};
985+ EXPECT_TRUE(stp.supports(com::ubuntu::location::Provider::Features::none));
986+ EXPECT_FALSE(stp.requires(com::ubuntu::location::Provider::Requirements::none));
987+ EXPECT_FALSE(stp.matches_criteria(com::ubuntu::location::Criteria{}));
988+ stp.on_wifi_and_cell_reporting_state_changed(com::ubuntu::location::WifiAndCellIdReportingState::on);
989+ stp.on_reference_location_updated(reference_position_update);
990+ stp.on_reference_heading_updated(reference_heading_update);
991+ stp.on_reference_velocity_updated(reference_velocity_update);
992+ stp.start_position_updates();
993+ stp.stop_position_updates();
994+ stp.start_heading_updates();
995+ stp.stop_heading_updates();
996+ stp.start_velocity_updates();
997+ stp.stop_velocity_updates();
998+}
999+
1000+TEST(StateTrackingProviderTest, state_after_construction_is_enabled)
1001+{
1002+ using namespace ::testing;
1003+ cul::StateTrackingProvider stp{std::make_shared<NiceMock<MockProvider>>()};
1004+ EXPECT_EQ(cul::StateTrackingProvider::State::enabled, stp.state());
1005+}
1006+
1007+TEST(StateTrackingProviderTest, state_after_start_is_active)
1008+{
1009+ using namespace ::testing;
1010+ cul::StateTrackingProvider stp{std::make_shared<NiceMock<MockProvider>>()};
1011+ stp.start_position_updates();
1012+ EXPECT_EQ(cul::StateTrackingProvider::State::active, stp.state());
1013+}
1014+
1015+TEST(StateTrackingProviderTest, stop_switches_to_enabled)
1016+{
1017+ using namespace ::testing;
1018+ cul::StateTrackingProvider stp{std::make_shared<NiceMock<MockProvider>>()};
1019+ stp.start_position_updates();
1020+ stp.stop_position_updates();
1021+ EXPECT_EQ(cul::StateTrackingProvider::State::enabled, stp.state());
1022+}

Subscribers

People subscribed via source and target branches