Merge lp:~thomas-voss/location-service/fwd-merge into lp:location-service/trunk

Proposed by Thomas Voß on 2016-01-13
Status: Needs review
Proposed branch: lp:~thomas-voss/location-service/fwd-merge
Merge into: lp:location-service/trunk
Diff against target: 2784 lines (+1908/-192)
48 files modified
CMakeLists.txt (+14/-0)
_clang-format (+56/-0)
astyle-config (+43/-0)
debian/changelog (+91/-0)
debian/source/format (+1/-1)
doc/Doxyfile.in (+2/-2)
doc/daemon_and_cli.md (+55/-0)
doc/debugging.md (+92/-0)
doc/hacking.md (+146/-0)
doc/intro.md (+67/-0)
doc/manual_testing.md (+174/-0)
doc/tips_n_tricks.md (+21/-0)
examples/service/service.cpp (+14/-15)
include/location_service/com/ubuntu/location/provider_factory.h (+3/-0)
po/ubuntu-location-service.pot (+7/-11)
src/location_service/com/ubuntu/location/CMakeLists.txt (+1/-0)
src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp (+12/-6)
src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h (+12/-0)
src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp (+1/-1)
src/location_service/com/ubuntu/location/engine.cpp (+23/-14)
src/location_service/com/ubuntu/location/engine.h (+3/-3)
src/location_service/com/ubuntu/location/provider_factory.cpp (+14/-0)
src/location_service/com/ubuntu/location/providers/config.cpp (+7/-0)
src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt (+3/-1)
src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp (+42/-0)
src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h (+62/-0)
src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp (+3/-5)
src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h (+1/-1)
src/location_service/com/ubuntu/location/providers/remote/provider.cpp (+23/-0)
src/location_service/com/ubuntu/location/service/daemon.cpp (+27/-82)
src/location_service/com/ubuntu/location/service/implementation.cpp (+25/-4)
src/location_service/com/ubuntu/location/service/provider_daemon.cpp (+17/-16)
src/location_service/com/ubuntu/location/service/runtime.cpp (+109/-0)
src/location_service/com/ubuntu/location/service/runtime.h (+90/-0)
src/location_service/com/ubuntu/location/service/session/skeleton.cpp (+21/-3)
src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp (+1/-1)
src/location_service/com/ubuntu/location/time_based_update_policy.cpp (+4/-3)
tests/CMakeLists.txt (+2/-0)
tests/acceptance_tests.cpp (+114/-12)
tests/delayed_service_test.cpp (+193/-0)
tests/engine_test.cpp (+3/-3)
tests/gps_provider_test.cpp (+83/-0)
tests/mock_event_receiver.h (+35/-0)
tests/position_test.cpp (+1/-1)
tests/remote_providerd_test.cpp (+1/-7)
tests/runtime_test.cpp (+118/-0)
tools/CMakeLists.txt (+1/-0)
tools/symbol_diff.in (+70/-0)
To merge this branch: bzr merge lp:~thomas-voss/location-service/fwd-merge
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve on 2016-01-13
Ubuntu Phablet Team 2016-01-13 Pending
Review via email: mp+282431@code.launchpad.net

Commit message

[ Alberto Mardegan ]
* Set debian source format to "3.0 (native)"
[ Scott Sweeny ]
* Allow providers to register themselves asynchronously (LP: #1415029)
* Account for changes in trust-store w.r.t. assembling the description
  of a trust prompt.
* Fix settings not being applied correctly.
* Ensure that event connections are cleaned up on destruction. (LP:
  #1480877)
[ Alberto Mardegan ]
* Send last known position on session start
[ CI Train Bot ]
* New rebuild forced.
[ Thomas Voß ]
* Factor out service::Runtime from daemon.cpp into its own .h/.cpp
  pair of files. Add test cases around correct operation of
  service::Runtime. added:
  src/location_service/com/ubuntu/location/service/runtime.cpp
  src/location_service/com/ubuntu/location/service/runtime.h
  tests/runtime_test.cpp
[ thomas-voss ]
* Factor out service::Runtime from daemon.cpp into its own .h/.cpp
  pair of files. Add test cases around correct operation of
  service::Runtime. added:
  src/location_service/com/ubuntu/location/service/runtime.cpp
  src/location_service/com/ubuntu/location/service/runtime.h
  tests/runtime_test.cpp
* Adjust default timeout for downloading GPS XTRA data.
[ Alberto Mardegan ]
* Make sure that injected time is given in milliseconds
[ Thomas Voß ]
* Cherry-pick rev. 196 and 199 from lp:location-service. The changes
  got accidentally removed by merging the outstanding documentation
  branch.
* Handle responses of clients to updates asynchronously. Rely on
  dummy::ConnectivityManager as harvesting is disabled anyway. (LP:
  #1462664, #1387643)
[ Thomas Voß ]
* Add documentation for debugging, hacking and debugging the location
  service. Pull manual testing instructions over from the wiki. Add
  tools for formatting the source.
[ thomas-voss ]
* Add documentation for debugging, hacking and debugging the location
  service. Pull manual testing instructions over from the wiki. Add
  tools for formatting the source.

Description of the change

[ Alberto Mardegan ]
* Set debian source format to "3.0 (native)"
[ Scott Sweeny ]
* Allow providers to register themselves asynchronously (LP: #1415029)
* Account for changes in trust-store w.r.t. assembling the description
  of a trust prompt.
* Fix settings not being applied correctly.
* Ensure that event connections are cleaned up on destruction. (LP:
  #1480877)
[ Alberto Mardegan ]
* Send last known position on session start
[ CI Train Bot ]
* New rebuild forced.
[ Thomas Voß ]
* Factor out service::Runtime from daemon.cpp into its own .h/.cpp
  pair of files. Add test cases around correct operation of
  service::Runtime. added:
  src/location_service/com/ubuntu/location/service/runtime.cpp
  src/location_service/com/ubuntu/location/service/runtime.h
  tests/runtime_test.cpp
[ thomas-voss ]
* Factor out service::Runtime from daemon.cpp into its own .h/.cpp
  pair of files. Add test cases around correct operation of
  service::Runtime. added:
  src/location_service/com/ubuntu/location/service/runtime.cpp
  src/location_service/com/ubuntu/location/service/runtime.h
  tests/runtime_test.cpp
* Adjust default timeout for downloading GPS XTRA data.
[ Alberto Mardegan ]
* Make sure that injected time is given in milliseconds
[ Thomas Voß ]
* Cherry-pick rev. 196 and 199 from lp:location-service. The changes
  got accidentally removed by merging the outstanding documentation
  branch.
* Handle responses of clients to updates asynchronously. Rely on
  dummy::ConnectivityManager as harvesting is disabled anyway. (LP:
  #1462664, #1387643)
[ Thomas Voß ]
* Add documentation for debugging, hacking and debugging the location
  service. Pull manual testing instructions over from the wiki. Add
  tools for formatting the source.
[ thomas-voss ]
* Add documentation for debugging, hacking and debugging the location
  service. Pull manual testing instructions over from the wiki. Add
  tools for formatting the source.

Unmerged revisions

219. By Thomas Voß on 2016-01-13

[ Alberto Mardegan ]
* Set debian source format to "3.0 (native)"
[ Scott Sweeny ]
* Allow providers to register themselves asynchronously (LP: #1415029)
* Account for changes in trust-store w.r.t. assembling the description
  of a trust prompt.
* Fix settings not being applied correctly.
* Ensure that event connections are cleaned up on destruction. (LP:
  #1480877)
[ Alberto Mardegan ]
* Send last known position on session start
[ CI Train Bot ]
* New rebuild forced.
[ Thomas Voß ]
* Factor out service::Runtime from daemon.cpp into its own .h/.cpp
  pair of files. Add test cases around correct operation of
  service::Runtime. added:
  src/location_service/com/ubuntu/location/service/runtime.cpp
  src/location_service/com/ubuntu/location/service/runtime.h
  tests/runtime_test.cpp
[ thomas-voss ]
* Factor out service::Runtime from daemon.cpp into its own .h/.cpp
  pair of files. Add test cases around correct operation of
  service::Runtime. added:
  src/location_service/com/ubuntu/location/service/runtime.cpp
  src/location_service/com/ubuntu/location/service/runtime.h
  tests/runtime_test.cpp
* Adjust default timeout for downloading GPS XTRA data.
[ Alberto Mardegan ]
* Make sure that injected time is given in milliseconds
[ Thomas Voß ]
* Cherry-pick rev. 196 and 199 from lp:location-service. The changes
  got accidentally removed by merging the outstanding documentation
  branch.
* Handle responses of clients to updates asynchronously. Rely on
  dummy::ConnectivityManager as harvesting is disabled anyway. (LP:
  #1462664, #1387643)
[ Thomas Voß ]
* Add documentation for debugging, hacking and debugging the location
  service. Pull manual testing instructions over from the wiki. Add
  tools for formatting the source.
[ thomas-voss ]
* Add documentation for debugging, hacking and debugging the location
  service. Pull manual testing instructions over from the wiki. Add
  tools for formatting the source.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-09-18 23:06:08 +0000
3+++ CMakeLists.txt 2016-01-13 12:31:53 +0000
4@@ -54,6 +54,20 @@
5 SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-local-typedefs")
6 endif (DISABLE_ERROR_ON_LOCAL_TYPEDEFS_WARNINGS)
7
8+#
9+# Code style fixer. We rely on clang-format to adjust the formatting of source code.
10+#
11+find_program(CLANG_FORMAT_COMMAND NAMES clang-format-3.6 clang-format-3.5)
12+if (NOT CLANG_FORMAT_COMMAND)
13+ message(WARNING "Cannot find clang-format >= clang-format-3.5: formatcode target will not be available")
14+endif()
15+
16+if (CLANG_FORMAT_COMMAND)
17+ file(GLOB_RECURSE UBUNTU_LOCATION_SERVICE_INTERFACE_HEADER_FILES ${CMAKE_SOURCE_DIR}/include/*.h)
18+ file(GLOB_RECURSE UBUNTU_LOCATION_SERVICE_IMPLEMENTATION_FILES ${CMAKE_SOURCE_DIR}/src/*.h ${CMAKE_SOURCE_DIR}/src/*.cpp)
19+ add_custom_target(formatcode ${CLANG_FORMAT_COMMAND} -i ${UBUNTU_LOCATION_SERVICE_INTERFACE_HEADER_FILES} ${UBUNTU_LOCATION_SERVICE_IMPLEMENTATION_FILES} SOURCES _clang-format)
20+endif()
21+
22 include_directories(
23 ${Boost_INCLUDE_DIRS}
24 ${DBUS_INCLUDE_DIRS}
25
26=== added file '_clang-format'
27--- _clang-format 1970-01-01 00:00:00 +0000
28+++ _clang-format 2016-01-13 12:31:53 +0000
29@@ -0,0 +1,56 @@
30+---
31+Language: Cpp
32+AccessModifierOffset: -4
33+ConstructorInitializerIndentWidth: 4
34+AlignEscapedNewlinesLeft: false
35+AlignTrailingComments: true
36+AllowAllParametersOfDeclarationOnNextLine: true
37+AllowShortBlocksOnASingleLine: false
38+AllowShortIfStatementsOnASingleLine: false
39+AllowShortLoopsOnASingleLine: false
40+AllowShortFunctionsOnASingleLine: All
41+AlwaysBreakTemplateDeclarations: false
42+AlwaysBreakBeforeMultilineStrings: false
43+BreakBeforeBinaryOperators: false
44+BreakBeforeTernaryOperators: true
45+BreakConstructorInitializersBeforeComma: false
46+BinPackParameters: true
47+ColumnLimit: 0
48+ConstructorInitializerAllOnOneLineOrOnePerLine: false
49+DerivePointerAlignment: false
50+ExperimentalAutoDetectBinPacking: false
51+IndentCaseLabels: false
52+IndentWrappedFunctionNames: false
53+IndentFunctionDeclarationAfterType: false
54+MaxEmptyLinesToKeep: 1
55+KeepEmptyLinesAtTheStartOfBlocks: true
56+NamespaceIndentation: None
57+ObjCSpaceAfterProperty: false
58+ObjCSpaceBeforeProtocolList: true
59+PenaltyBreakBeforeFirstCallParameter: 19
60+PenaltyBreakComment: 300
61+PenaltyBreakString: 1000
62+PenaltyBreakFirstLessLess: 120
63+PenaltyExcessCharacter: 1000000
64+PenaltyReturnTypeOnItsOwnLine: 60
65+PointerAlignment: Left
66+SpacesBeforeTrailingComments: 1
67+Cpp11BracedListStyle: true
68+Standard: Cpp11
69+IndentWidth: 4
70+TabWidth: 8
71+UseTab: Never
72+BreakBeforeBraces: Allman
73+SpacesInParentheses: false
74+SpacesInAngles: false
75+SpaceInEmptyParentheses: false
76+SpacesInCStyleCastParentheses: false
77+SpacesInContainerLiterals: true
78+SpaceBeforeAssignmentOperators: true
79+ContinuationIndentWidth: 4
80+CommentPragmas: '^ IWYU pragma:'
81+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
82+SpaceBeforeParens: ControlStatements
83+DisableFormat: false
84+...
85+
86
87=== added file 'astyle-config'
88--- astyle-config 1970-01-01 00:00:00 +0000
89+++ astyle-config 2016-01-13 12:31:53 +0000
90@@ -0,0 +1,43 @@
91+# Options for formatting code with astyle.
92+#
93+# This helps to make code match the style guide.
94+#
95+# Use like this:
96+#
97+# astyle --options=astyle-config mfile.h myfile.cpp
98+#
99+# Occasionally, astyle does something silly (particularly with lambdas), so it's
100+# still necessary to scan the changes for things that are wrong.
101+# But, for most files, it does a good job.
102+#
103+# Please consider using this before checking code in for review. Code reviews shouldn't
104+# have to deal with layout issues, they are just a distraction. It's better to be able
105+# to focus on semantics in a code review, with style issues out of the way.
106+
107+--formatted
108+--style=allman
109+--min-conditional-indent=2
110+--indent-switches
111+--max-instatement-indent=120
112+--pad-header
113+--align-pointer=type
114+--align-reference=type
115+--convert-tabs
116+--close-templates
117+--max-code-length=120
118+
119+# --pad-oper
120+#
121+# Commented out for now. It changes
122+#
123+# for (int i=0; i<10; ++i)
124+# to
125+# for (int i = 0; i < 10; ++i)
126+#
127+# Unfortunately, it also messes with rvalue references:
128+#
129+# ResourcePtr& operator=(ResourcePtr&& r);
130+#
131+# becomes:
132+#
133+# ResourcePtr& operator=(ResourcePtr && r);
134
135=== modified file 'debian/changelog'
136--- debian/changelog 2015-07-27 18:07:37 +0000
137+++ debian/changelog 2016-01-13 12:31:53 +0000
138@@ -36,6 +36,97 @@
139
140 -- CI Train Bot <ci-train-bot@canonical.com> Thu, 28 May 2015 11:40:58 +0000
141
142+location-service (2.1+15.04.20160106-0ubuntu1) vivid; urgency=medium
143+
144+ [ Alberto Mardegan ]
145+ * Set debian source format to "3.0 (native)"
146+
147+ [ Scott Sweeny ]
148+ * Allow providers to register themselves asynchronously (LP: #1415029)
149+
150+ -- Thomas Voß <ci-train-bot@canonical.com> Wed, 06 Jan 2016 16:15:29 +0000
151+
152+location-service (2.1+15.04.20151211-0ubuntu1) vivid; urgency=medium
153+
154+ * Account for changes in trust-store w.r.t. assembling the description
155+ of a trust prompt.
156+
157+ -- Thomas Voß <ci-train-bot@canonical.com> Fri, 11 Dec 2015 08:57:44 +0000
158+
159+location-service (2.1+15.04.20151209-0ubuntu1) vivid; urgency=medium
160+
161+ * Fix settings not being applied correctly.
162+
163+ -- Thomas Voß <ci-train-bot@canonical.com> Wed, 09 Dec 2015 15:22:22 +0000
164+
165+location-service (2.1+15.04.20151202.1-0ubuntu1) vivid; urgency=medium
166+
167+ * Ensure that event connections are cleaned up on destruction. (LP:
168+ #1480877)
169+
170+ -- Thomas Voß <ci-train-bot@canonical.com> Wed, 02 Dec 2015 12:12:21 +0000
171+
172+location-service (2.1+15.04.20151127-0ubuntu1) vivid; urgency=medium
173+
174+ [ Alberto Mardegan ]
175+ * Send last known position on session start
176+
177+ [ CI Train Bot ]
178+ * New rebuild forced.
179+
180+ [ Thomas Voß ]
181+ * Factor out service::Runtime from daemon.cpp into its own .h/.cpp
182+ pair of files. Add test cases around correct operation of
183+ service::Runtime. added:
184+ src/location_service/com/ubuntu/location/service/runtime.cpp
185+ src/location_service/com/ubuntu/location/service/runtime.h
186+ tests/runtime_test.cpp
187+
188+ [ thomas-voss ]
189+ * Factor out service::Runtime from daemon.cpp into its own .h/.cpp
190+ pair of files. Add test cases around correct operation of
191+ service::Runtime. added:
192+ src/location_service/com/ubuntu/location/service/runtime.cpp
193+ src/location_service/com/ubuntu/location/service/runtime.h
194+ tests/runtime_test.cpp
195+
196+ -- Thomas Voß <ci-train-bot@canonical.com> Fri, 27 Nov 2015 13:00:33 +0000
197+
198+location-service (2.1+15.04.20151113-0ubuntu1) vivid; urgency=medium
199+
200+ * Adjust default timeout for downloading GPS XTRA data.
201+
202+ -- Thomas Voß <ci-train-bot@canonical.com> Fri, 13 Nov 2015 10:33:56 +0000
203+
204+location-service (2.1+15.04.20151109.2-0ubuntu1) vivid; urgency=medium
205+
206+ [ Alberto Mardegan ]
207+ * Make sure that injected time is given in milliseconds
208+
209+ [ Thomas Voß ]
210+ * Cherry-pick rev. 196 and 199 from lp:location-service. The changes
211+ got accidentally removed by merging the outstanding documentation
212+ branch.
213+ * Handle responses of clients to updates asynchronously. Rely on
214+ dummy::ConnectivityManager as harvesting is disabled anyway. (LP:
215+ #1462664, #1387643)
216+
217+ -- David Barth <david.barth@canonical.com> Mon, 09 Nov 2015 20:48:48 +0000
218+
219+location-service (2.1+15.04.20151022-0ubuntu1) vivid; urgency=medium
220+
221+ [ Thomas Voß ]
222+ * Add documentation for debugging, hacking and debugging the location
223+ service. Pull manual testing instructions over from the wiki. Add
224+ tools for formatting the source.
225+
226+ [ thomas-voss ]
227+ * Add documentation for debugging, hacking and debugging the location
228+ service. Pull manual testing instructions over from the wiki. Add
229+ tools for formatting the source.
230+
231+ -- Thomas Voß <ci-train-bot@canonical.com> Thu, 22 Oct 2015 07:16:50 +0000
232+
233 location-service (2.1+15.04.20150427.1-0ubuntu1) vivid; urgency=medium
234
235 [ CI Train Bot ]
236
237=== modified file 'debian/source/format'
238--- debian/source/format 2014-07-30 14:15:06 +0000
239+++ debian/source/format 2016-01-13 12:31:53 +0000
240@@ -1,1 +1,1 @@
241-3.0 (quilt)
242+3.0 (native)
243
244=== modified file 'doc/Doxyfile.in'
245--- doc/Doxyfile.in 2014-05-19 09:55:25 +0000
246+++ doc/Doxyfile.in 2016-01-13 12:31:53 +0000
247@@ -748,7 +748,7 @@
248 # directories that contain image that are included in the documentation (see
249 # the \image command).
250
251-IMAGE_PATH =
252+IMAGE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/images
253
254 # The INPUT_FILTER tag can be used to specify a program that doxygen should
255 # invoke to filter for each input file. Doxygen will invoke the filter program
256@@ -1463,7 +1463,7 @@
257 # generate an XML file that captures the structure of
258 # the code including all documentation.
259
260-GENERATE_XML = NO
261+GENERATE_XML = YES
262
263 # The XML_OUTPUT tag is used to specify where the XML pages will be put.
264 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
265
266=== added file 'doc/daemon_and_cli.md'
267--- doc/daemon_and_cli.md 1970-01-01 00:00:00 +0000
268+++ doc/daemon_and_cli.md 2016-01-13 12:31:53 +0000
269@@ -0,0 +1,55 @@
270+# Service Daemon and CLI
271+
272+The location service offers a daemon executable and a corresponding
273+command-line interface for interacting with it. The daemon does not
274+necessarily require root privileges, but might so depending on your
275+configuration.
276+
277+Run the following command to receive an overview of the arguments to
278+the daemon:
279+
280+ ubuntu-location-serviced --help
281+
282+An example invocation of the daemon, configuring a GPS provider that
283+relies on the Android HAL to talk to the chipset, exposing the service
284+on the system DBus instance:
285+
286+ ubuntu-location-serviced --bus system --provider gps::Provider
287+
288+The cli allows for querying properties of a running service instance, e.g.:
289+
290+ ubuntu-location-serviced-cli --bus system --get --property is_online
291+
292+## Configuring an Out-Of-Process Provider
293+
294+If you want to run a provider out of process, the daemon executable
295+allows you to do so by instantiating a so-called remote provider. The
296+following invocation of the service tries to connect to the provider
297+instance described by the given unique DBus name and path.
298+
299+ ubuntu-location-serviced \
300+ --bus system \
301+ --provider remote::Provider \
302+ --remote::Provider::bus=system \
303+ --remote::Provider::name=com.ubuntu.location.provider.Gps \
304+ --remote::Provider::path=/
305+
306+Please note that the service allows for decorating provider names to
307+uniquely identify per provider configuration options and to allow for
308+loading more than one provider of a certain kind. The following
309+configuration configures two remote providers, one relying on GPS
310+(decorated with @gps) and another one relying on network-based
311+positioning (decorated with @network):
312+
313+ ubuntu-location-serviced \
314+ --bus system \
315+ --provider remote::Provider@gps \
316+ --remote::Provider@gps::bus=system \
317+ --remote::Provider@gps::name=com.ubuntu.location.provider.Gps \
318+ --remote::Provider@gps::path=/ \
319+ --provider remote::Provider@network \
320+ --remote::Provider@network::bus=system \
321+ --remote::Provider@network::name=com.ubuntu.location.provider.Network \
322+ --remote::Provider@network::path=/
323+
324+
325
326=== added file 'doc/debugging.md'
327--- doc/debugging.md 1970-01-01 00:00:00 +0000
328+++ doc/debugging.md 2016-01-13 12:31:53 +0000
329@@ -0,0 +1,92 @@
330+# Debugging
331+
332+Location not working? Here's how to debug.
333+
334+## Layers
335+
336+Test in OSMTouch (QML app using Qt API) before testing in webapps or
337+webbrowser app. Different results? File a bug where it doesn't
338+work. Same result of no location? Next step.
339+
340+## Check that stack works with dummy provider
341+
342+Edit /etc/init/ubuntu-location-provider.override to start
343+location-serviced with just the dummy provider; this should
344+work. Doesn't work? File a bug against location-service. Works? Reset
345+config to defaults and try the next thing.
346+
347+## Hardware GPS breaking all of location-service
348+
349+GPS provider is built-in into location-service and might break all of
350+it if it goes south (working on splitting it out); try enabling only
351+the HERE provider on the location-serviced command-line and see if
352+that works. Works? File a bug against location-service. Doesn't work?
353+Move on.
354+
355+## HERE test
356+
357+To test whether the low-level HERE stack gets a location, put
358+http://people.canonical.com/~lool/espoo-cli on your phone (will be
359+included along HERE bits in the future) and run with:
360+
361+ chmod a+x espoo-cli
362+ GLOG_logtostderr=1 GLOG_v=100 LD_LIBRARY_PATH=/custom/vendor/here/location-provider/lib/arm-linux-gnueabihf ./espoo-cli 5
363+
364+NB: 5 is the number of location updates after which the tool exits;
365+updates should come in at approx 15s interval. Output looks like:
366+
367+ I1101 21:30:01.285964 4403 cli.cpp:117] Requested number of updates is 2
368+ I1101 21:30:01.299002 4403 cli.cpp:133] Starting location updates
369+ I1101 21:30:01.301888 4403 cli.cpp:141] Starting GLib main loop
370+ I1101 21:30:11.304612 4403 cli.cpp:158] Location: tstamp=1414891811 lat=xyz long=foo hor. acc.=2569 alt=nan vert. acc.=nan tech=cell
371+ I1101 21:30:11.306061 4403 cli.cpp:170] Remaining updates: 1
372+ I1101 21:30:26.736821 4403 cli.cpp:158] Location: tstamp=1414891826 lat=xyz long=foo hor. acc.=2824 alt=nan vert. acc.=nan tech=cell
373+ I1101 21:30:26.738348 4403 cli.cpp:148] Stopping location updates
374+
375+Low-level HERE stack works but location-serviced with just HERE
376+provider doesn't work? File a bug against espoo projet (HERE) and/or
377+location-service. Low-level HERE stack doesn't work? Move on
378+
379+## location-service and espoo-service debug
380+
381+Collect some debug data by editing /etc/init/ubuntu-espoo-service.conf
382+and /etc/init/ubuntu-location-service.override and changing the start
383+sequence to add some env vars:
384+
385+ export GLOG_v=200
386+ export GLOG_logtostderr=1
387+
388+before the exec. Reboot, and start some app. You should have some log
389+files under /var/log/upstart/ubuntu-espoo-service.log and
390+/var/log/upstart/ubuntu-location-service.log to attach to a bug
391+report; e.g. a working espoo log looks like this:
392+
393+ WARNING: Logging before InitGoogleLogging() is written to STDERR
394+ I1105 16:30:10.221474 1620 provider.cpp:568] StartPositionUpdates
395+ I1105 16:30:10.224901 1620 provider.cpp:122] Successfully started position updates.
396+ I1105 16:30:10.228739 1620 provider.cpp:596] StartVelocityUpdates
397+ I1105 16:30:13.046851 1621 provider.cpp:83] Received location: Position(lat: Coordinate(12.34 deg), lon: Coordinate(12.34 deg), alt: Coordinate(nan m), hor.acc.: 1430 m, ver.acc.: nan m)
398+
399+No position there? check connectivity API works by running:
400+
401+ cd /tmp
402+ wget http://people.ubuntu.com/~lool/connectivity
403+ GLOG_v=200 GLOG_logtostderr=1 ./connectivity
404+
405+you should see something like:
406+
407+ I1105 16:47:26.431466 11140 cached_radio_cell.cpp:160] (mcc: 123, mnc: 2, lac: 1234, id: 123456, asu: 1)
408+ I1105 16:47:26.533818 11140 connectivity.cpp:47] Is wifi enabled: true
409+ I1105 16:47:26.533963 11140 connectivity.cpp:48] Is wifi hw enabled: true
410+ I1105 16:47:26.534010 11140 connectivity.cpp:49] Is wwan enabled: true
411+ I1105 16:47:26.534050 11140 connectivity.cpp:50] Is wwan hw enabled: true
412+ I1105 16:47:26.534442 11140 connectivity.cpp:122] umts(mcc: 123, mnc: 2, lac: 1234, id: 123456, asu: 1)
413+ I1105 16:47:26.534633 11140 connectivity.cpp:155] (bssid: 12:12:12:12:12:12, ssid: xyz, last seen: 1415224046, mode: Mode::infrastructure, frequency: 2442, strength: 63)
414+ I1105 16:47:26.534828 11140 connectivity.cpp:155] (bssid: 12:12:12:12:12:12, ssid: boing, last seen: 1415224046, mode: Mode::infrastructure, frequency: 2467, strength: 57)
415+
416+Also, please attach output of /usr/share/ofono/scripts/list-modems > list-modems-output.txt
417+Please note that the command might take ~1 minute to complete.
418+
419+TODO: document dbus-monitor / d-feet capturing of client / system traffic with snooping config.
420+
421+
422
423=== added file 'doc/hacking.md'
424--- doc/hacking.md 1970-01-01 00:00:00 +0000
425+++ doc/hacking.md 2016-01-13 12:31:53 +0000
426@@ -0,0 +1,146 @@
427+# Hacking
428+
429+
430+## Building the code
431+
432+By default, the code is built in release mode. To build a debug version, use
433+
434+ $ mkdir builddebug
435+ $ cd builddebug
436+ $ cmake -DCMAKE_BUILD_TYPE=debug ..
437+ $ make
438+
439+For a release version, use -DCMAKE_BUILD_TYPE=release
440+
441+## Running the tests
442+
443+ $ make
444+ $ make test
445+
446+Note that "make test" alone is dangerous because it does not rebuild
447+any tests if either the library or the test files themselves need
448+rebuilding. It's not possible to fix this with cmake because cmake cannot
449+add build dependencies to built-in targets. To make sure that everything
450+is up-to-date, run "make" before running "make test"!
451+
452+## Coverage
453+
454+To build with the flags for coverage testing enabled and get coverage:
455+
456+ $ mkdir buildcoverage
457+ $ cd buildcoverage
458+ $ cmake -DCMAKE_BUILD_TYPE=coverage
459+ $ make
460+ $ make test
461+ $ make coverage
462+
463+Unfortunately, it is not possible to get 100% coverage for some files,
464+mainly due to gcc's generation of two destructors for dynamic and non-
465+dynamic instances. For abstract base classes and for classes that
466+prevent stack and static allocation, this causes one of the destructors
467+to be reported as uncovered.
468+
469+There are also issues with some functions in header files that are
470+incorrectly reported as uncovered due to inlining, as well as
471+the impossibility of covering defensive assert(false) statements,
472+such as an assert in the default branch of a switch, where the
473+switch is meant to handle all possible cases explicitly.
474+
475+If you run a binary and get lots of warnings about a "merge mismatch for summaries",
476+this is caused by having made changes to the source that add or remove code
477+that was previously run, so the new coverage output cannot sensibly be merged
478+into the old coverage output. You can get rid of this problem by running
479+
480+ $ make clean-coverage
481+
482+This deletes all the .gcda files, allowing the merge to (sometimes) succeed again.
483+If this doesn't work either, the only remedy is to do a clean build.
484+
485+If lcov complains about unrecognized lines involving '=====',
486+you can patch geninfo and gcovr as explained here:
487+
488+https://bugs.launchpad.net/gcovr/+bug/1086695/comments/2
489+
490+## Code style
491+
492+We use a format tool that fixes a whole lot of issues
493+regarding code style. The formatting changes made by
494+the tool are generally sensible (even though they may not be your
495+personal preference in all cases). If there is a case where the formatting
496+really messes things up, consider re-arranging the code to avoid the problem.
497+The convenience of running the entire code base through the pretty-printer
498+far outweighs any minor glitches with pretty printing, and it means that
499+we get consistent code style for free, rather than endlessly having to
500+watch out for formatting issues during code reviews.
501+
502+As of clang-format-3.7, you can use
503+
504+ // clang-format off
505+ void unformatted_code ;
506+ // clang-format on
507+
508+to suppress formatting for a section of code.
509+
510+To format specific files:
511+
512+ ${CMAKE_BINARY_DIR}/tools/formatcode x.cpp x.h
513+
514+If no arguments are provided, formatcode reads stdin and writes
515+stdout, so you can easily pipe code into the tool from within an
516+editor. For example, to reformat the entire file in vi (assuming
517+${CMAKE_BINARY_DIR}/tools is in your PATH):
518+
519+ 1G!Gformatcode
520+
521+To re-format all source and header files in the tree:
522+
523+ $ make formatcode
524+
525+## Thread and address sanitizer
526+
527+Set SANITIZER to "thread" or "address" to build with the
528+corresponding sanitizer enabled.
529+
530+## Updating symbols file
531+
532+To easily spot new/removed/changed symbols in the library, the debian
533+package maintains a .symbols file that lists all exported symbols
534+present in the library .so. If you add new public symbols to the library,
535+it's necessary to refresh the symbols file, otherwise the package will
536+fail to build. The easiest way to do that is using bzr-builddeb:
537+
538+ $ bzr bd -- -us -uc -j8 # Don't sign source package or changes file, 8 compiles in parallel
539+ $ # this will exit with an error if symbols file isn't up-to-date
540+ $ cd ../build-area/location-service-[version]
541+ $ ./obj-[arch]/tools/symbol_diff
542+
543+This creates a diff of the symbols in /tmp/symbols.diff.
544+(The demangled symbols from the debian build are in ./new_symbols.)
545+
546+Review any changes in /tmp/symbols.diff. If they are OK:
547+
548+ $ cd -
549+ $ patch -p0 < /tmp/symbols.diff
550+
551+## ABI compliance test
552+
553+To use this, install abi-compliance-checker package from the archives.
554+
555+You can use abi-compliance-checker to test whether a particular build
556+is ABI compatible with another build. The tool does some source-level
557+analysis in addition to checking library symbols, so it catches things
558+that are potentially dangerous, but won't be picked up by just looking
559+at the symbol table.
560+
561+Assume you have built devel in src/devel, and you have a later build
562+in src/mybranch and want to check that mybranch is still compatible.
563+To run the compliance test:
564+
565+ $ cd src
566+ $ abi-compliance-checker -lib libunity-scopes.so -old devel/build/test/abi-compliance/abi.xml -new mybranch/build/test/abi-compliance/abi.xml
567+
568+The script will take about two minutes to run. Now point your browser at
569+
570+ src/compat_reports/libunity-scopes.so/[version]_to_[version]/compat_report.html
571+
572+The report provides a nicely layed-out page with all the details.
573
574=== added directory 'doc/images'
575=== added file 'doc/images/LocationServiceHighLevel.png'
576Binary files doc/images/LocationServiceHighLevel.png 1970-01-01 00:00:00 +0000 and doc/images/LocationServiceHighLevel.png 2016-01-13 12:31:53 +0000 differ
577=== added file 'doc/intro.md'
578--- doc/intro.md 1970-01-01 00:00:00 +0000
579+++ doc/intro.md 2016-01-13 12:31:53 +0000
580@@ -0,0 +1,67 @@
581+# Introduction {#mainpage}
582+
583+Ubuntu's location service is a central hub for multiplexing access to
584+positioning subsystems available via hard- and software. It provides a
585+client API offering positioning capabilities to applications and other
586+system components, abstracting away the details of individual
587+positioning solutions.
588+
589+## Vocabulary
590+
591+To make the remainder of this documentation as easily understandable
592+as possible, we start over with introducing some vocabulary:
593+
594+- Engine:
595+ Responsible for handling input from multiple positioning
596+ subsystems and maintaining the state of the overall system. Think
597+ about it like the heart of the system.
598+
599+- Provider:
600+ A positioning subsystem that feeds into the positioning
601+ engine. Common examples are a GPS provider or a network-based
602+ positioning provider.
603+
604+- Service:
605+ The point of entry for applications and services that would
606+ like to receive position data.
607+
608+- Session:
609+ In order to receive position information, every application
610+ or service has to create a session with the location Service.
611+
612+- Update: An update is a timestamped entity to a certain type of data.
613+
614+- [WGS84, http://en.wikipedia.org/wiki/World_Geodetic_System]: The coordinate system that is used throughout the entire location subsystem.
615+
616+## Architectural Overview
617+
618+The high-level architecture of the service is shown in the following diagram:
619+
620+![High-level architectural overview](images/LocationServiceHighLevel.png)
621+
622+In this diagram, the configuration of the engine refers to:
623+
624+ * The current state of any satellite-based positioning subsystems. Can either be off or on.
625+ * The current state of reporting facilities responsible for harvesting wifi and cell id measurements together with location information and sending them off to remote services. Can either be off or on.
626+ * The overall state of the engine. Can either be off, on or active.
627+
628+The Service takes this configuration and exposes it to client
629+applications. In addition, mainly for debugging purposes, the set of
630+currently visible satellites (if any) is maintained and exposed to
631+privileged client applications.
632+
633+## Privacy & Access Control
634+
635+Location information is highly privacy relevant. For this reason, the
636+location service is deeply integrated with AppArmor and Ubuntu's
637+overall trust infrastructure. Every incoming session request is
638+validated and if in doubt, the user is asked to explicitly grant trust
639+to the application requesting access to positioning
640+information. Please see [@ref com::ubuntu::location::service::PermissionManager]
641+for further details.
642+
643+In addition, the location service allows for selectively adjusting the
644+accuracy and reporting setup of the location Engine to provide further
645+fine-grained control over the exposed data to user. Within this setup,
646+a user is able to entirely disable all positioning.
647+
648
649=== added file 'doc/manual_testing.md'
650--- doc/manual_testing.md 1970-01-01 00:00:00 +0000
651+++ doc/manual_testing.md 2016-01-13 12:31:53 +0000
652@@ -0,0 +1,174 @@
653+# Manual Testplan
654+
655+[TOC]
656+
657+While the automatic test suite of the location service is
658+comprehensive and covers large parts of the functionality of the
659+service itself, we still provide an additional level of acceptance
660+testing covering the entire location stack/experience as a part of
661+this document.
662+
663+## Dependents/Clients
664+
665+ - qtubuntu-sensors
666+ - Qt/QML applications:
667+ - Browser
668+ - osmTouch
669+
670+## Test Plan
671+
672+This test plan is not supposed to be complete; use it to guide your
673+manual testing so you don't miss big functional areas that are part of
674+the component; also this should be used as guideline to inspire the
675+exploratory testing which should be adapted smartly based on the real
676+content of a MP.
677+
678+Please note that if you're testing the GPS provider, the location
679+service relies on GPS hardware to obtain a location fix. For that, it
680+might be required that you execute the manual steps listed before
681+close to a window or ideally outside, with good satellite visibility
682+conditions.
683+
684+__Note: It can take up to 15 minutes for the GPS device to get a lock, due to lack of assisted GPS__
685+
686+ - Install latest image on phone
687+ - Install freshly built MPs that are needed for landing
688+
689+Depending on the default configuration of location-service on the
690+image, you may skip parts of this test plan. E.g. if GPS hardware is
691+disabled, skip this part. You can see which providers are enabled by
692+looking at the list of providers on the location-serviced command-line
693+(`ps fauxw | grep location-service`, then look at the `--provider`
694+flags).
695+
696+### Dummy provider
697+
698+This tests forces location-service to use only the dummy provider;
699+this providers a baseline test for the app to trust-store to
700+location-service path.
701+
702+ - phablet-shell into the phone:
703+ - `sudo service ubuntu-location-service stop && sudo /usr/bin/ubuntu-location-serviced --bus system --provider dummy::Provider --dummy::Provider::ReferenceLocationLat=48.857503 --dummy::Provider::ReferenceLocationLon=2.295072`
704+ - As phablet, start the trust store again (it stops when location-service is stopped) with: `start ubuntu-location-service-trust-stored`
705+ - Ensure that all AP tests for the webbrowser pass as expected
706+ - Point the browser to maps.google.com (alternatively: here.com, maps.bing.fr).
707+ - Request centering the map on current position and observe if it works correctly (should show the Eiffel tower)
708+ - Install osmTouch from the app store
709+ - Launch osmTouch and check if it centers on the Eiffel tower.
710+ - Install a maps webapp such as HERE or Google Maps webapp from the app store
711+ - Launch maps webapp and check if it centers on the Eiffel tower.
712+
713+### GPS Test Plan
714+
715+This applies only if GPS provider is enabled.
716+
717+ - (If applicable: Remember to add the silo you are testing)
718+ - `sudo apt-get install ubuntu-location-service-tests`
719+ - If you want to send off crowdsourced information, i.e., information about visible wifis and visible radio cells for the obtained location fixes to Mozilla's location service and our own instance:
720+ - `sudo GLOG_v=40 GLOG_logtostderr=1 GPS_TEST_ENABLE_HARVESTING_DURING_TESTS=1 /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_without_supl_benchmark_requires_hardware`
721+ - If you '''don't''' want to send off crowdsourced information:
722+ - `sudo GLOG_v=40 GLOG_logtostderr=1 /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_without_supl_benchmark_requires_hardware`
723+
724+ - The test will output a lot of diagnostic information to the
725+ terminal and will take ~30 minutes. If satellite visibility is
726+ limited, it can take even longer. The test will automatically
727+ report success or failure.
728+
729+### Preliminary AGPS Test Plan
730+
731+**Does not apply to Krillin**
732+
733+Please note that the Krillin GPS chipset driver and its integration
734+within Ubuntu does not support vanilla AGPS (i.e., SUPL) right
735+now. For that, this test case is irrelevant for Krillin and is likely
736+to fail.
737+
738+This applied only if GPS provider and some other provider (giving
739+_A_ssistance) are enabled.
740+
741+ - Add the silo.
742+ - `sudo apt-get install ubuntu-location-service-tests`
743+ - Obtain a (rough) location estimate for your current location on Google maps.
744+ - Make sure to replace INSERT_ESTIMATE_HERE with the respective
745+ values obtained from Google maps.
746+ - If you want to send off crowdsourced information, i.e., information
747+ about visible wifis and visible radio cells for the obtained
748+ location fixes to Mozilla's location service and our own instance:
749+ - `sudo GLOG_v=40 GLOG_logtostderr=1 GPS_TEST_ENABLE_HARVESTING_DURING_TESTS=1 GPS_TEST_REF_LAT=INSERT_ESTIMATE_HERE GPS_TEST_REF_LON=INSERT_ESTIMATE_HERE /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_with_supl_benchmark_requires_hardware`
750+ - If you '''don't''' want to send off crowdsourced information:
751+ - `sudo GLOG_v=40 GLOG_logtostderr=1 GPS_TEST_REF_LAT=INSERT_ESTIMATE_HERE GPS_TEST_REF_LON=INSERT_ESTIMATE_HERE /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_with_supl_benchmark_requires_hardware`
752+
753+ - The test will output a lot of diagnostic information to the
754+ terminal and will take ~10 minutes or less. The test will
755+ automatically report success or failure.
756+
757+### Espoo / HERE provider
758+
759+This applies only if the Espoo / HERE remote provider is enabled. This
760+provider should be enabled by default and may either work standalone
761+as the only provider or as an assistance for the GPS hardware to lock.
762+
763+ - Add the silo; special exception for lxc-android-config: see https://wiki.ubuntu.com/Touch/Testing/lxc-android-config
764+ - If noted, deploy an updated custom tarball:
765+ - Download the tarball under /tmp ('''NOT''' under /)
766+ - Unpack there: `cd /tmp; sudo tar xvf custom-vendor-here-*.tar.xz`
767+ - Remove older bits: `sudo rm -rf /custom/vendor/here/`
768+ - Update custom bits: `sudo mv /tmp/system/custom/vendor/here /custom/vendor`
769+ - Reboot
770+ - After boot, check you have these three processes running on top of location-service:
771+ - slpgwd
772+ - posclientd
773+ - ubuntu-espoo-service
774+ - Make sure SIM is unlocked and attached to the network (has some reliable signal) and that WiFi is turned on.
775+ - Install OSMTouch app
776+ - Run OSMTouch app, hit the position button every other second until you get a blue circle showing your current location;
777+
778+# Connectivity API
779+
780+For integration of network-based positioning providers, the location
781+service offers a connectivity API that provides access to wifi and
782+cell measurements as well as information on the current overall
783+connectivity status of the device. Please execute the following
784+commands on a newly flashed device with a writable image:
785+
786+ - `sudo apt-get update && sudo apt-get build-dep location-service && sudo apt-get install libubuntu-location-service-dev ubuntu-location-service-examples`
787+ - `mkdir /tmp/build && cd /tmp/build && cmake /usr/share/ubuntu-location-service/examples/standalone/connectivity/ && make`
788+ - `GLOG_logtostderr=1 ./connectivity`
789+
790+Verify that the output looks similar to:
791+
792+ phablet@ubuntu-phablet:/tmp/build$ ./connectivity
793+ Is wifi enabled: true
794+ Is wifi hw enabled: true
795+ Is wwan enabled: false
796+ Is wwan hw enabled: true
797+ umts(mcc: 262, mnc: 2, lac: 5313, id: 131948771, asu: 7)
798+ (bssid: BC:F2:AF:AF:19:A2, ssid: devolo-bcf2afaf19a2, last seen: 1408955086, mode: Mode::infrastructure, frequency: 2462, strength: 72)
799+ (bssid: 00:22:3F:35:43:58, ssid: JustAnotherWLAN, last seen: 1408955086, mode: Mode::infrastructure, frequency: 2412, strength: 24)
800+ (bssid: 82:C7:A6:40:8C:4E, ssid: EasyBox-44D054, last seen: 1408955206, mode: Mode::infrastructure, frequency: 2417, strength: 17)
801+ (bssid: 00:24:01:B8:32:8D, ssid: gra, last seen: 1408955086, mode: Mode::infrastructure, frequency: 2412, strength: 12)
802+ (bssid: C0:25:06:3C:28:22, ssid: FRITZ!Box 6360 Cable, last seen: 1408954966, mode: Mode::infrastructure, frequency: 2412, strength: 17)
803+ (bssid: 00:1C:4A:A5:B7:59, ssid: FRITZ!Box Fon WLAN 7170, last seen: 1408954966, mode: Mode::infrastructure, frequency: 2437, strength: 10)
804+ Last seen changed for wifi (bssid: BC:F2:AF:AF:19:A2, ssid: devolo-bcf2afaf19a2, last seen: 1408955257, mode: Mode::infrastructure, frequency: 2462, strength: 72)
805+ Last seen changed for wifi (bssid: 00:22:3F:35:43:58, ssid: JustAnotherWLAN, last seen: 1408955257, mode: Mode::infrastructure, frequency: 2412, strength: 24)
806+ Signal strength changed for wifi: (bssid: BC:F2:AF:AF:19:A2, ssid: devolo-bcf2afaf19a2, last seen: 1408955257, mode: Mode::infrastructure, frequency: 2462, strength: 73)
807+
808+# Trust Store Integration
809+
810+Please note that we are assuming a freshly wiped system for testing
811+here. If you cannot fulfill that pre-condition, please run `rm -rf
812+/home/phablet/.local/share/UbuntuLocationService && sudo shutdown -r` prior to running the
813+tests:
814+
815+## Unconfined
816+
817+ - Open the browser, go to maps.google.com
818+ - Observe the in-browser dialog asking for granting access to location.
819+
820+## Confined Web-App
821+
822+ - Open the Nokia Here web app, observe the trust dialog appearing.
823+
824+## Confined Application
825+
826+ - Open osmtouch and observe the osmtouch surface sliding up, presenting you with a trust dialog.
827
828=== added file 'doc/tips_n_tricks.md'
829--- doc/tips_n_tricks.md 1970-01-01 00:00:00 +0000
830+++ doc/tips_n_tricks.md 2016-01-13 12:31:53 +0000
831@@ -0,0 +1,21 @@
832+# Tips'n'Tricks
833+
834+## Mark HERE license as accepted from cmdline
835+
836+ sudo LC_ALL=C gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User32011 --method org.freedesktop.DBus.Properties.Set com.ubuntu.location.providers.here.AccountsService LicenseAccepted '<true>'
837+
838+## Force startup after ofono and NM are started
839+
840+This is a *workaround* to get connectivity API to collect; mount your
841+system read-write and edit
842+/etc/init/ubuntu-location-provider-here-slpgwd.conf:
843+
844+ sudo mount -o remount,rw /
845+ sudo vi /etc/init/ubuntu-location-provider-here-slpgwd.conf
846+
847+change: `start on started dbus and (started ofono or started network-manager)`
848+to: `start on started dbus and started ofono and started network-manager`
849+
850+ sudo mount -o remount,ro /
851+ sync
852+ sudo reboot
853
854=== modified file 'examples/service/service.cpp'
855--- examples/service/service.cpp 2014-11-14 11:26:45 +0000
856+++ examples/service/service.cpp 2016-01-13 12:31:53 +0000
857@@ -99,7 +99,10 @@
858 auto selected_providers = options.value_for_key<std::vector<std::string>>("provider");
859
860 std::map<std::string, cul::ProviderFactory::Configuration> config_lut;
861- std::set<cul::Provider::Ptr> instantiated_providers;
862+
863+ culs::DefaultConfiguration config;
864+ auto settings = std::make_shared<cul::BoostPtreeSettings>(options.value_for_key<std::string>("config-file"));
865+ auto engine = config.the_engine(std::set<cul::Provider::Ptr>{}, config.the_provider_selection_policy(), settings);
866
867 for (const std::string& provider : selected_providers)
868 {
869@@ -129,15 +132,15 @@
870
871 try
872 {
873- auto p = cul::ProviderFactory::instance().create_provider_for_name_with_config(
874- provider,
875- config_lut[provider]);
876-
877- if (p)
878- instantiated_providers.insert(p);
879- else
880- throw std::runtime_error("Problem instantiating provider");
881-
882+ auto result = std::async(std::launch::async, [provider, config_lut, engine] {
883+ return cul::ProviderFactory::instance().create_provider_for_name_with_config(
884+ provider,
885+ config_lut.at(provider),
886+ [engine](cul::Provider::Ptr provider)
887+ {
888+ engine->add_provider(provider);
889+ });
890+ });
891 } catch(const std::runtime_error& e)
892 {
893 std::cerr << "Exception instantiating provider: " << e.what() << " ... Aborting now." << std::endl;
894@@ -163,15 +166,11 @@
895 };
896 outgoing->install_executor(dbus::asio::make_executor(outgoing));
897
898- auto settings = std::make_shared<cul::BoostPtreeSettings>(options.value_for_key<std::string>("config-file"));
899-
900- culs::DefaultConfiguration config;
901-
902 culs::Implementation::Configuration configuration
903 {
904 incoming,
905 outgoing,
906- config.the_engine(instantiated_providers, config.the_provider_selection_policy(), settings),
907+ engine,
908 config.the_permission_manager(incoming),
909 culs::Harvester::Configuration
910 {
911
912=== modified file 'include/location_service/com/ubuntu/location/provider_factory.h'
913--- include/location_service/com/ubuntu/location/provider_factory.h 2014-10-27 21:58:16 +0000
914+++ include/location_service/com/ubuntu/location/provider_factory.h 2016-01-13 12:31:53 +0000
915@@ -54,6 +54,9 @@
916 // --provider=remote::Provider@gps --remote::Provider@gps::name="com.ubuntu.android.gps.Provider" --remote::Provider@gps::path="/com/ubuntu/android/gps/Provider"
917 Provider::Ptr create_provider_for_name_with_config(const std::string& name, const Configuration& config);
918
919+ // Async version of above.
920+ void create_provider_for_name_with_config(const std::string& name, const Configuration& config, const std::function<void(Provider::Ptr)>& cb);
921+
922 void enumerate(const std::function<void(const std::string&, const Factory&)>& enumerator);
923
924 private:
925
926=== modified file 'po/ubuntu-location-service.pot'
927--- po/ubuntu-location-service.pot 2014-09-19 09:06:30 +0000
928+++ po/ubuntu-location-service.pot 2016-01-13 12:31:53 +0000
929@@ -1,13 +1,14 @@
930-# Copyright (C) 2014 Canonical Ltd.
931-# This file is distributed under the same license as the ubuntu-location-service package.
932-# Thomas Voß <thomas.voss@canonical.com>, 2014.
933+# SOME DESCRIPTIVE TITLE.
934+# Copyright (C) YEAR Canonical Ltd.
935+# This file is distributed under the same license as the PACKAGE package.
936+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
937 #
938 #, fuzzy
939 msgid ""
940 msgstr ""
941 "Project-Id-Version: ubuntu-location-service\n"
942 "Report-Msgid-Bugs-To: \n"
943-"POT-Creation-Date: 2014-09-19 01:04+0200\n"
944+"POT-Creation-Date: 2015-11-27 14:07+0100\n"
945 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
946 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
947 "Language-Team: LANGUAGE <LL@li.org>\n"
948@@ -16,11 +17,6 @@
949 "Content-Type: text/plain; charset=CHARSET\n"
950 "Content-Transfer-Encoding: 8bit\n"
951
952-#: /tmp/i18n/src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp:170
953-msgid "An unconfined application wants to access your current location."
954-msgstr ""
955-
956-#: /tmp/i18n/src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp:173
957-#, boost-format
958-msgid "%1% wants to access your current location."
959+#: /home/tvoss/ubuntu/scratch/fix-prompt-string/src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp:149
960+msgid "wants to access your current location."
961 msgstr ""
962
963=== modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt'
964--- src/location_service/com/ubuntu/location/CMakeLists.txt 2015-04-23 14:48:44 +0000
965+++ src/location_service/com/ubuntu/location/CMakeLists.txt 2016-01-13 12:31:53 +0000
966@@ -38,6 +38,7 @@
967 service/harvester.cpp
968 service/demultiplexing_reporter.h
969 service/demultiplexing_reporter.cpp
970+ service/runtime.cpp
971 service/runtime_tests.h
972 service/runtime_tests.cpp
973 service/trust_store_permission_manager.cpp
974
975=== modified file 'src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp'
976--- src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp 2015-05-28 10:57:24 +0000
977+++ src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp 2016-01-13 12:31:53 +0000
978@@ -123,7 +123,14 @@
979 const org::freedesktop::NetworkManager::Device& device,
980 const org::freedesktop::NetworkManager::AccessPoint& ap)
981 : device_(device),
982- access_point_(ap)
983+ access_point_(ap),
984+ connections
985+ {
986+ access_point_.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
987+ {
988+ on_access_point_properties_changed(dict);
989+ })
990+ }
991 {
992 last_seen_ = translate_time_stamp(access_point_.last_seen->get());
993
994@@ -138,12 +145,11 @@
995 {
996 static_cast<int>(access_point_.strength->get())
997 };
998+}
999
1000- // Wire up all the connections
1001- access_point_.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
1002- {
1003- on_access_point_properties_changed(dict);
1004- });
1005+detail::CachedWirelessNetwork::~CachedWirelessNetwork()
1006+{
1007+ access_point_.properties_changed->disconnect(connections.ap_properties_changed);
1008 }
1009
1010 void detail::CachedWirelessNetwork::on_access_point_properties_changed(const std::map<std::string, core::dbus::types::Variant>& dict)
1011
1012=== modified file 'src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h'
1013--- src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h 2014-08-14 20:25:22 +0000
1014+++ src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h 2016-01-13 12:31:53 +0000
1015@@ -41,6 +41,8 @@
1016 const org::freedesktop::NetworkManager::Device& device,
1017 const org::freedesktop::NetworkManager::AccessPoint& ap);
1018
1019+ ~CachedWirelessNetwork();
1020+
1021 // Timestamp when the network became visible.
1022 const core::Property<std::chrono::system_clock::time_point>& last_seen() const override;
1023
1024@@ -67,6 +69,16 @@
1025 // The actual access point stub.
1026 org::freedesktop::NetworkManager::AccessPoint access_point_;
1027
1028+ // Encapsulates all event connections that have to be cut on destruction.
1029+ struct
1030+ {
1031+ core::dbus::Signal
1032+ <
1033+ org::freedesktop::NetworkManager::AccessPoint::PropertiesChanged,
1034+ org::freedesktop::NetworkManager::AccessPoint::PropertiesChanged::ArgumentType
1035+ >::SubscriptionToken ap_properties_changed;
1036+ } connections;
1037+
1038 core::Property<std::chrono::system_clock::time_point> last_seen_;
1039 core::Property<std::string> bssid_;
1040 core::Property<std::string> ssid_;
1041
1042=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp'
1043--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2015-05-27 18:40:37 +0000
1044+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2016-01-13 12:31:53 +0000
1045@@ -595,7 +595,7 @@
1046
1047 xdg::NetworkManager::AccessPoint ap
1048 {
1049- network_manager->service->add_object_for_path(ap_path)
1050+ network_manager->service->object_for_path(ap_path)
1051 };
1052
1053 auto wifi = std::make_shared<detail::CachedWirelessNetwork>(itd->second, ap);
1054
1055=== modified file 'src/location_service/com/ubuntu/location/engine.cpp'
1056--- src/location_service/com/ubuntu/location/engine.cpp 2015-04-23 14:48:44 +0000
1057+++ src/location_service/com/ubuntu/location/engine.cpp 2016-01-13 12:31:53 +0000
1058@@ -169,19 +169,28 @@
1059
1060 // We wire up changes in the engine's configuration to the respective slots
1061 // of the provider.
1062- auto cp = updates.reference_location.changed().connect([provider](const cul::Update<cul::Position>& pos)
1063- {
1064- provider->on_reference_location_updated(pos);
1065- });
1066-
1067- auto cv = updates.reference_velocity.changed().connect([provider](const cul::Update<cul::Velocity>& velocity)
1068- {
1069- provider->on_reference_velocity_updated(velocity);
1070- });
1071-
1072- auto ch = updates.reference_heading.changed().connect([provider](const cul::Update<cul::Heading>& heading)
1073- {
1074- provider->on_reference_heading_updated(heading);
1075+ auto cp = updates.last_known_location.changed().connect([provider](const cul::Optional<cul::Update<cul::Position>>& pos)
1076+ {
1077+ if (pos)
1078+ {
1079+ provider->on_reference_location_updated(pos.get());
1080+ }
1081+ });
1082+
1083+ auto cv = updates.last_known_velocity.changed().connect([provider](const cul::Optional<cul::Update<cul::Velocity>>& velocity)
1084+ {
1085+ if (velocity)
1086+ {
1087+ provider->on_reference_velocity_updated(velocity.get());
1088+ }
1089+ });
1090+
1091+ auto ch = updates.last_known_heading.changed().connect([provider](const cul::Optional<cul::Update<cul::Heading>>& heading)
1092+ {
1093+ if (heading)
1094+ {
1095+ provider->on_reference_heading_updated(heading.get());
1096+ }
1097 });
1098
1099 auto cr = configuration.wifi_and_cell_id_reporting_state.changed().connect([provider](cul::WifiAndCellIdReportingState state)
1100@@ -207,7 +216,7 @@
1101 // We should come up with a better heuristic here.
1102 auto cpr = provider->updates().position.connect([this](const cul::Update<cul::Position>& src)
1103 {
1104- updates.reference_location = update_policy->verify_update(src);
1105+ updates.last_known_location = update_policy->verify_update(src);
1106 });
1107
1108 std::lock_guard<std::mutex> lg(guard);
1109
1110=== modified file 'src/location_service/com/ubuntu/location/engine.h'
1111--- src/location_service/com/ubuntu/location/engine.h 2015-04-23 14:48:44 +0000
1112+++ src/location_service/com/ubuntu/location/engine.h 2016-01-13 12:31:53 +0000
1113@@ -127,11 +127,11 @@
1114 struct Updates
1115 {
1116 /** The current best known reference location */
1117- core::Property<Update<Position>> reference_location{};
1118+ core::Property<Optional<Update<Position>>> last_known_location{};
1119 /** The current best known velocity estimate. */
1120- core::Property<Update<Velocity>> reference_velocity{};
1121+ core::Property<Optional<Update<Velocity>>> last_known_velocity{};
1122 /** The current best known heading estimate. */
1123- core::Property<Update<Heading>> reference_heading{};
1124+ core::Property<Optional<Update<Heading>>> last_known_heading{};
1125 /** The current set of visible SpaceVehicles. */
1126 core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>> visible_space_vehicles{};
1127 };
1128
1129=== modified file 'src/location_service/com/ubuntu/location/provider_factory.cpp'
1130--- src/location_service/com/ubuntu/location/provider_factory.cpp 2014-10-27 21:58:16 +0000
1131+++ src/location_service/com/ubuntu/location/provider_factory.cpp 2016-01-13 12:31:53 +0000
1132@@ -52,6 +52,20 @@
1133 return cul::Provider::Ptr{factory_store.at(undecorated_name)(config)};
1134 }
1135
1136+void cul::ProviderFactory::create_provider_for_name_with_config(
1137+ const std::string& name,
1138+ const cul::ProviderFactory::Configuration& config,
1139+ const std::function<void(Provider::Ptr)>& cb)
1140+{
1141+ auto undecorated_name = name.substr(0, name.find("@"));
1142+
1143+ std::lock_guard<std::mutex> lg(guard);
1144+ if (factory_store.count(undecorated_name) == 0)
1145+ return;
1146+
1147+ cb(cul::Provider::Ptr{factory_store.at(undecorated_name)(config)});
1148+}
1149+
1150 void cul::ProviderFactory::enumerate(
1151 const std::function<void(const std::string&, const cul::ProviderFactory::Factory&)>& enumerator)
1152 {
1153
1154=== modified file 'src/location_service/com/ubuntu/location/providers/config.cpp'
1155--- src/location_service/com/ubuntu/location/providers/config.cpp 2014-09-15 08:58:50 +0000
1156+++ src/location_service/com/ubuntu/location/providers/config.cpp 2016-01-13 12:31:53 +0000
1157@@ -19,6 +19,7 @@
1158 #include <com/ubuntu/location/provider_factory.h>
1159
1160 #include "dummy/provider.h"
1161+#include "dummy/delayed_provider.h"
1162
1163 #include <map>
1164
1165@@ -41,6 +42,12 @@
1166 com::ubuntu::location::providers::dummy::Provider::create_instance
1167 };
1168
1169+static FactoryInjector dummy_delayed_injector
1170+{
1171+ "dummy::DelayedProvider",
1172+ com::ubuntu::location::providers::dummy::DelayedProvider::create_instance
1173+};
1174+
1175 #include <com/ubuntu/location/providers/remote/provider.h>
1176 static FactoryInjector remote_injector
1177 {
1178
1179=== modified file 'src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt'
1180--- src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt 2014-02-07 17:16:49 +0000
1181+++ src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt 2016-01-13 12:31:53 +0000
1182@@ -2,7 +2,9 @@
1183 dummy
1184
1185 provider.h
1186- provider.cpp)
1187+ provider.cpp
1188+ delayed_provider.h
1189+ delayed_provider.cpp)
1190
1191 set(
1192 ENABLED_PROVIDER_TARGETS
1193
1194=== added file 'src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp'
1195--- src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp 1970-01-01 00:00:00 +0000
1196+++ src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp 2016-01-13 12:31:53 +0000
1197@@ -0,0 +1,42 @@
1198+/*
1199+ * Copyright © 2015 Canonical Ltd.
1200+ *
1201+ * This program is free software: you can redistribute it and/or modify it
1202+ * under the terms of the GNU Lesser General Public License version 3,
1203+ * as published by the Free Software Foundation.
1204+ *
1205+ * This program is distributed in the hope that it will be useful,
1206+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1207+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1208+ * GNU Lesser General Public License for more details.
1209+ *
1210+ * You should have received a copy of the GNU Lesser General Public License
1211+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1212+ *
1213+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com>
1214+ */
1215+
1216+#include <com/ubuntu/location/logging.h>
1217+
1218+#include <chrono>
1219+#include <thread>
1220+
1221+#include "delayed_provider.h"
1222+
1223+namespace location = com::ubuntu::location;
1224+namespace dummy = com::ubuntu::location::providers::dummy;
1225+
1226+std::string dummy::DelayedProvider::class_name()
1227+{
1228+ return "dummy::DelayedProvider";
1229+}
1230+
1231+location::Provider::Ptr dummy::DelayedProvider::create_instance(const ProviderFactory::Configuration& config)
1232+{
1233+ int delay = config.get(dummy::DelayConfiguration::Keys::delay, 0);
1234+ VLOG(1) << __PRETTY_FUNCTION__ << ": delay for " << delay << "ms";
1235+
1236+ std::this_thread::sleep_for(std::chrono::milliseconds{delay});
1237+
1238+ return dummy::Provider::create_instance(config);
1239+}
1240
1241=== added file 'src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h'
1242--- src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h 1970-01-01 00:00:00 +0000
1243+++ src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h 2016-01-13 12:31:53 +0000
1244@@ -0,0 +1,62 @@
1245+/*
1246+ * Copyright © 2015 Canonical Ltd.
1247+ *
1248+ * This program is free software: you can redistribute it and/or modify it
1249+ * under the terms of the GNU Lesser General Public License version 3,
1250+ * as published by the Free Software Foundation.
1251+ *
1252+ * This program is distributed in the hope that it will be useful,
1253+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1254+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1255+ * GNU Lesser General Public License for more details.
1256+ *
1257+ * You should have received a copy of the GNU Lesser General Public License
1258+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1259+ *
1260+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com>
1261+ */
1262+
1263+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_DUMMY_DELAYED_PROVIDER_H_
1264+#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_DUMMY_DELAYED_PROVIDER_H_
1265+
1266+#include "provider.h"
1267+
1268+namespace com
1269+{
1270+namespace ubuntu
1271+{
1272+namespace location
1273+{
1274+namespace providers
1275+{
1276+namespace dummy
1277+{
1278+ struct DelayConfiguration
1279+ {
1280+ struct Keys
1281+ {
1282+ static constexpr const char* delay
1283+ {
1284+ "DelayInMs"
1285+ };
1286+ };
1287+ };
1288+
1289+class DelayedProvider : public Provider
1290+{
1291+ public:
1292+ // For integration with the Provider factory
1293+ static std::string class_name();
1294+ // Waits for "DelayInMs" from the provided property bundle then
1295+ // instantiates a new provider instance, populating the configuration object
1296+ // from the provided property bundle.
1297+ static DelayedProvider::Ptr create_instance(const ProviderFactory::Configuration&);
1298+ // Creates a new provider instance from the given configuration.
1299+ DelayedProvider(const Configuration config = Configuration{});
1300+};
1301+}
1302+}
1303+}
1304+}
1305+}
1306+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_DUMMY_DELAYED_PROVIDER_H_
1307
1308=== modified file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp'
1309--- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp 2014-10-27 21:58:16 +0000
1310+++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp 2016-01-13 12:31:53 +0000
1311@@ -66,8 +66,6 @@
1312 if (config.count("XTRA_SERVER_3") > 0)
1313 result.xtra_hosts.push_back(config.get<std::string>("XTRA_SERVER_3"));
1314
1315- result.timeout = std::chrono::milliseconds{1500};
1316-
1317 return result;
1318 }
1319
1320@@ -333,14 +331,14 @@
1321 } else
1322 {
1323 auto now = location::Clock::now().time_since_epoch();
1324- auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
1325+ auto ms_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(now);
1326
1327 static const int zero_uncertainty = 0;
1328
1329 u_hardware_gps_inject_time(
1330 thiz->impl.gps_handle,
1331- now.count(),
1332- now.count(),
1333+ ms_since_epoch.count(),
1334+ ms_since_epoch.count(),
1335 zero_uncertainty);
1336 }
1337 }
1338
1339=== modified file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h'
1340--- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h 2015-04-22 13:30:04 +0000
1341+++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h 2016-01-13 12:31:53 +0000
1342@@ -49,7 +49,7 @@
1343 /** @brief Timeout on gps xtra download operations. */
1344 std::chrono::milliseconds timeout
1345 {
1346- 5000
1347+ 30000
1348 };
1349
1350 /** Set of hosts serving GPS xtra data. */
1351
1352=== modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.cpp'
1353--- src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2015-04-14 18:54:00 +0000
1354+++ src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2016-01-13 12:31:53 +0000
1355@@ -23,6 +23,7 @@
1356 #include <com/ubuntu/location/logging.h>
1357
1358 #include <core/dbus/object.h>
1359+#include <core/dbus/service_watcher.h>
1360 #include <core/dbus/signal.h>
1361 #include <core/dbus/asio/executor.h>
1362
1363@@ -191,6 +192,28 @@
1364 auto service = dbus::Service::use_service(bus, name);
1365 auto object = service->object_for_path(path);
1366
1367+ // Check if the service has come up
1368+ if (!bus->has_owner_for_name(name)) {
1369+ // If it hasn't wait for it to come up
1370+ bool valid = false;
1371+ std::mutex guard;
1372+ std::condition_variable cv;
1373+ dbus::DBus daemon(bus);
1374+ dbus::ServiceWatcher::Ptr service_watcher(
1375+ daemon.make_service_watcher(name, dbus::DBus::WatchMode::registration));
1376+
1377+ service_watcher->service_registered().connect([&valid, &guard, &cv]()
1378+ {
1379+ std::unique_lock<std::mutex> ul(guard);
1380+ valid = true;
1381+ cv.notify_all();
1382+ });
1383+
1384+ std::unique_lock<std::mutex> ul(guard);
1385+ if (not cv.wait_for(ul, std::chrono::seconds{30}, [&valid]() { return valid; }))
1386+ throw std::runtime_error("Remote service failed to start");
1387+ }
1388+
1389 return create_instance_with_config(remote::stub::Configuration{object});
1390 }
1391
1392
1393=== modified file 'src/location_service/com/ubuntu/location/service/daemon.cpp'
1394--- src/location_service/com/ubuntu/location/service/daemon.cpp 2015-04-16 10:03:29 +0000
1395+++ src/location_service/com/ubuntu/location/service/daemon.cpp 2016-01-13 12:31:53 +0000
1396@@ -20,6 +20,9 @@
1397 #include <com/ubuntu/location/boost_ptree_settings.h>
1398 #include <com/ubuntu/location/provider_factory.h>
1399
1400+#include <com/ubuntu/location/logging.h>
1401+#include <com/ubuntu/location/connectivity/dummy_connectivity_manager.h>
1402+
1403 #include <com/ubuntu/location/service/default_configuration.h>
1404 #include <com/ubuntu/location/service/demultiplexing_reporter.h>
1405 #include <com/ubuntu/location/service/ichnaea_reporter.h>
1406@@ -30,6 +33,7 @@
1407
1408 #include "program_options.h"
1409 #include "daemon.h"
1410+#include "runtime.h"
1411
1412 #include <core/dbus/announcer.h>
1413 #include <core/dbus/resolver.h>
1414@@ -37,6 +41,8 @@
1415
1416 #include <core/posix/signal.h>
1417
1418+#include <boost/asio.hpp>
1419+
1420 #include <system_error>
1421 #include <thread>
1422
1423@@ -175,116 +181,55 @@
1424 trap->stop();
1425 });
1426
1427- const location::Configuration empty_provider_configuration;
1428-
1429- std::set<location::Provider::Ptr> instantiated_providers;
1430-
1431+ auto runtime = location::service::Runtime::create(4);
1432+
1433+ location::service::DefaultConfiguration dc;
1434+ auto engine = dc.the_engine(std::set<location::Provider::Ptr>{}, dc.the_provider_selection_policy(), config.settings);
1435 for (const std::string& provider : config.providers)
1436 {
1437 std::cout << "Instantiating and configuring: " << provider << std::endl;
1438
1439 try
1440 {
1441- auto p = location::ProviderFactory::instance().create_provider_for_name_with_config(
1442- provider,
1443- config.provider_options.count(provider) > 0 ?
1444- config.provider_options.at(provider) : empty_provider_configuration);
1445-
1446- if (p)
1447- instantiated_providers.insert(p);
1448- else
1449- throw std::runtime_error("Problem instantiating provider");
1450-
1451+ auto result = std::async(std::launch::async, [provider, config, engine] {
1452+ return location::ProviderFactory::instance().create_provider_for_name_with_config(
1453+ provider,
1454+ config.provider_options.count(provider) > 0 ?
1455+ config.provider_options.at(provider) : location::Configuration {},
1456+ [engine](Provider::Ptr provider)
1457+ {
1458+ engine->add_provider(provider);
1459+ }
1460+ );
1461+ });
1462 } catch(const std::runtime_error& e)
1463 {
1464 std::cerr << "Issue instantiating provider: " << e.what() << std::endl;
1465 }
1466 }
1467
1468- config.incoming->install_executor(dbus::asio::make_executor(config.incoming));
1469- config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing));
1470+ config.incoming->install_executor(dbus::asio::make_executor(config.incoming, runtime->service()));
1471+ config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing, runtime->service()));
1472
1473- location::service::DefaultConfiguration dc;
1474+ runtime->start();
1475
1476 location::service::Implementation::Configuration configuration
1477 {
1478 config.incoming,
1479 config.outgoing,
1480- dc.the_engine(instantiated_providers, dc.the_provider_selection_policy(), config.settings),
1481+ engine,
1482 dc.the_permission_manager(config.outgoing),
1483 location::service::Harvester::Configuration
1484 {
1485- location::connectivity::platform_default_manager(),
1486- // We submit location/wifi/cell measurements to both
1487- // Mozilla's location service and to Ubuntu's own instance.
1488- std::make_shared<service::DemultiplexingReporter>(
1489- std::initializer_list<service::Harvester::Reporter::Ptr>
1490- {
1491- std::make_shared<service::ichnaea::Reporter>(
1492- service::ichnaea::Reporter::Configuration
1493- {
1494- "https://location.services.mozilla.com",
1495- "UbuntuLocationService",
1496- "UbuntuLocationService"
1497- }
1498- ),
1499- std::make_shared<service::ichnaea::Reporter>(
1500- service::ichnaea::Reporter::Configuration
1501- {
1502- "https://162.213.35.107",
1503- "UbuntuLocationService",
1504- "UbuntuLocationService"
1505- }
1506- )
1507- })
1508+ std::make_shared<dummy::ConnectivityManager>(),
1509+ std::make_shared<NullReporter>()
1510 }
1511 };
1512
1513 auto location_service = std::make_shared<location::service::Implementation>(configuration);
1514- // We need to ensure that any exception raised by the executor does not crash the app
1515- // and also gets logged.
1516- auto execute = [] (std::shared_ptr<core::dbus::Bus> bus) {
1517- while(true)
1518- {
1519- try
1520- {
1521- VLOG(10) << "Starting a bus executor";
1522- bus->run();
1523- break; // run() exited normally
1524- }
1525- catch (const std::exception& e)
1526- {
1527- LOG(WARNING) << e.what();
1528- }
1529- catch (...)
1530- {
1531- LOG(WARNING) << "Unexpected exception was raised by the bus executor";
1532- }
1533- }
1534- };
1535-
1536- std::thread t1{execute, config.incoming};
1537- std::thread t2{execute, config.incoming};
1538- std::thread t3{execute, config.incoming};
1539- std::thread t4{execute, config.outgoing};
1540
1541 trap->run();
1542
1543- config.incoming->stop();
1544- config.outgoing->stop();
1545-
1546- if (t1.joinable())
1547- t1.join();
1548-
1549- if (t2.joinable())
1550- t2.join();
1551-
1552- if (t3.joinable())
1553- t3.join();
1554-
1555- if (t4.joinable())
1556- t4.join();
1557-
1558 return EXIT_SUCCESS;
1559 }
1560
1561
1562=== modified file 'src/location_service/com/ubuntu/location/service/implementation.cpp'
1563--- src/location_service/com/ubuntu/location/service/implementation.cpp 2014-08-13 13:08:22 +0000
1564+++ src/location_service/com/ubuntu/location/service/implementation.cpp 2016-01-13 12:31:53 +0000
1565@@ -113,10 +113,13 @@
1566 {
1567 visible_space_vehicles() = svs;
1568 }),
1569- configuration.engine->updates.reference_location.changed().connect(
1570- [this](const cul::Update<cul::Position>& update)
1571+ configuration.engine->updates.last_known_location.changed().connect(
1572+ [this](const cul::Optional<cul::Update<cul::Position>>& update)
1573 {
1574- harvester.report_position_update(update);
1575+ if (update)
1576+ {
1577+ harvester.report_position_update(update.get());
1578+ }
1579 })
1580 }
1581 {
1582@@ -149,5 +152,23 @@
1583 new ProxyProvider{provider_selection}
1584 };
1585
1586- return session::Interface::Ptr{new culs::session::Implementation(proxy_provider)};
1587+ session::Interface::Ptr session_iface{new session::Implementation(proxy_provider)};
1588+ std::weak_ptr<session::Interface> session_weak{session_iface};
1589+ session_iface->updates().position_status.changed().connect([this, session_weak](const session::Interface::Updates::Status& status)
1590+ {
1591+ cul::Optional<cul::Update<cul::Position>> last_known_position = configuration.engine->updates.last_known_location.get();
1592+ bool has_last_known_position = last_known_position ? true : false;
1593+ bool is_session_enabled = status == culs::session::Interface::Updates::Status::enabled;
1594+ bool is_session_on_or_active = configuration.engine->configuration.engine_state != Engine::Status::off;
1595+
1596+ if (has_last_known_position && is_session_enabled && is_session_on_or_active)
1597+ {
1598+ // Immediately send the last known position to the client
1599+ if (auto session_iface = session_weak.lock())
1600+ {
1601+ session_iface->updates().position = last_known_position.get();
1602+ }
1603+ }
1604+ });
1605+ return session_iface;
1606 }
1607
1608=== modified file 'src/location_service/com/ubuntu/location/service/provider_daemon.cpp'
1609--- src/location_service/com/ubuntu/location/service/provider_daemon.cpp 2014-10-27 21:58:16 +0000
1610+++ src/location_service/com/ubuntu/location/service/provider_daemon.cpp 2016-01-13 12:31:53 +0000
1611@@ -25,6 +25,7 @@
1612
1613 #include <com/ubuntu/location/service/configuration.h>
1614 #include <com/ubuntu/location/service/program_options.h>
1615+#include <com/ubuntu/location/service/runtime.h>
1616
1617 #include <core/dbus/asio/executor.h>
1618
1619@@ -65,7 +66,6 @@
1620 location::service::ProviderDaemon::Configuration result;
1621
1622 result.connection = factory(mutable_daemon_options().bus());
1623- result.connection->install_executor(core::dbus::asio::make_executor(result.connection));
1624
1625 auto service = core::dbus::Service::add_service(
1626 result.connection,
1627@@ -108,7 +108,15 @@
1628 return result;
1629 }
1630
1631-int location::service::ProviderDaemon::main(const location::service::ProviderDaemon::Configuration& configuration)
1632+namespace
1633+{
1634+std::shared_ptr<location::service::Runtime> runtime()
1635+{
1636+ static const auto inst = location::service::Runtime::create(2);
1637+ return inst;
1638+}
1639+}
1640+int location::service::ProviderDaemon::main(const location::service::ProviderDaemon::Configuration& config)
1641 {
1642 auto trap = core::posix::trap_signals_for_all_subsequent_threads(
1643 {
1644@@ -121,27 +129,20 @@
1645 trap->stop();
1646 });
1647
1648- std::thread worker
1649- {
1650- [configuration]()
1651- {
1652- configuration.connection->run();
1653- }
1654- };
1655+ config.connection->install_executor(core::dbus::asio::make_executor(config.connection, runtime()->service()));
1656
1657 auto skeleton = location::providers::remote::skeleton::create_with_configuration(location::providers::remote::skeleton::Configuration
1658 {
1659- configuration.object,
1660- configuration.connection,
1661- configuration.provider
1662+ config.object,
1663+ config.connection,
1664+ config.provider
1665 });
1666
1667+ runtime()->start();
1668+
1669 trap->run();
1670
1671- configuration.connection->stop();
1672-
1673- if (worker.joinable())
1674- worker.join();
1675+ config.connection->stop();
1676
1677 return EXIT_SUCCESS;
1678 }
1679
1680=== added file 'src/location_service/com/ubuntu/location/service/runtime.cpp'
1681--- src/location_service/com/ubuntu/location/service/runtime.cpp 1970-01-01 00:00:00 +0000
1682+++ src/location_service/com/ubuntu/location/service/runtime.cpp 2016-01-13 12:31:53 +0000
1683@@ -0,0 +1,109 @@
1684+/*
1685+ * Copyright © 2015 Canonical Ltd.
1686+ *
1687+ * This program is free software: you can redistribute it and/or modify it
1688+ * under the terms of the GNU Lesser General Public License version 3,
1689+ * as published by the Free Software Foundation.
1690+ *
1691+ * This program is distributed in the hope that it will be useful,
1692+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1693+ * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the
1694+ * GNU Lesser General Public License for more details.
1695+ *
1696+ * You should have received a copy of the GNU Lesser General Public License
1697+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1698+ *
1699+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
1700+ */
1701+#include <com/ubuntu/location/service/runtime.h>
1702+
1703+#include <com/ubuntu/location/logging.h>
1704+
1705+namespace culs = com::ubuntu::location::service;
1706+
1707+namespace
1708+{
1709+// exception_safe_run runs service, catching all exceptions and
1710+// restarting operation until an explicit shutdown has been requested.
1711+//
1712+// TODO(tvoss): Catching all exceptions is risky as they might signal unrecoverable
1713+// errors. We should enable calling code to decide whether an exception should be considered
1714+// fatal or not.
1715+void exception_safe_run(boost::asio::io_service& service)
1716+{
1717+ while (true)
1718+ {
1719+ try
1720+ {
1721+ service.run();
1722+ // a clean return from run only happens in case of
1723+ // stop() being called (we are keeping the service alive with
1724+ // a service::work instance).
1725+ break;
1726+ }
1727+ catch (const std::exception& e)
1728+ {
1729+ LOG(WARNING) << e.what();
1730+ }
1731+ catch (...)
1732+ {
1733+ LOG(WARNING) << "Unknown exception caught while executing boost::asio::io_service";
1734+ }
1735+ }
1736+}
1737+}
1738+
1739+std::shared_ptr<culs::Runtime> culs::Runtime::create(std::uint32_t pool_size)
1740+{
1741+ return std::shared_ptr<culs::Runtime>(new culs::Runtime(pool_size));
1742+}
1743+
1744+culs::Runtime::Runtime(std::uint32_t pool_size)
1745+ : pool_size_{pool_size},
1746+ service_{pool_size_},
1747+ strand_{service_},
1748+ keep_alive_{service_}
1749+{
1750+}
1751+
1752+culs::Runtime::~Runtime()
1753+{
1754+ try
1755+ {
1756+ stop();
1757+ } catch(...)
1758+ {
1759+ // Dropping all exceptions to satisfy the nothrow guarantee.
1760+ }
1761+}
1762+
1763+void culs::Runtime::start()
1764+{
1765+ for (unsigned int i = 0; i < pool_size_; i++)
1766+ workers_.push_back(std::thread{exception_safe_run, std::ref(service_)});
1767+}
1768+
1769+void culs::Runtime::stop()
1770+{
1771+ service_.stop();
1772+
1773+ for (auto& worker : workers_)
1774+ if (worker.joinable())
1775+ worker.join();
1776+}
1777+
1778+std::function<void(std::function<void()>)> culs::Runtime::to_dispatcher_functional()
1779+{
1780+ // We have to make sure that we stay alive for as long as
1781+ // calling code requires the dispatcher to work.
1782+ auto sp = shared_from_this();
1783+ return [sp](std::function<void()> task)
1784+ {
1785+ sp->strand_.post(task);
1786+ };
1787+}
1788+
1789+boost::asio::io_service& culs::Runtime::service()
1790+{
1791+ return service_;
1792+}
1793
1794=== added file 'src/location_service/com/ubuntu/location/service/runtime.h'
1795--- src/location_service/com/ubuntu/location/service/runtime.h 1970-01-01 00:00:00 +0000
1796+++ src/location_service/com/ubuntu/location/service/runtime.h 2016-01-13 12:31:53 +0000
1797@@ -0,0 +1,90 @@
1798+/*
1799+ * Copyright © 2015 Canonical Ltd.
1800+ *
1801+ * This program is free software: you can redistribute it and/or modify it
1802+ * under the terms of the GNU Lesser General Public License version 3,
1803+ * as published by the Free Software Foundation.
1804+ *
1805+ * This program is distributed in the hope that it will be useful,
1806+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1807+ * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the
1808+ * GNU Lesser General Public License for more details.
1809+ *
1810+ * You should have received a copy of the GNU Lesser General Public License
1811+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1812+ *
1813+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
1814+ */
1815+#ifndef COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_
1816+#define COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_
1817+
1818+#include <boost/asio.hpp>
1819+
1820+#include <functional>
1821+#include <memory>
1822+#include <thread>
1823+#include <vector>
1824+
1825+#include <cstdint>
1826+
1827+namespace com
1828+{
1829+namespace ubuntu
1830+{
1831+namespace location
1832+{
1833+namespace service
1834+{
1835+// We bundle our "global" runtime dependencies here, specifically
1836+// a dispatcher to decouple multiple in-process providers from one
1837+// another , forcing execution to a well known set of threads.
1838+class Runtime : public std::enable_shared_from_this<Runtime>
1839+{
1840+public:
1841+ // Our default concurrency setup.
1842+ static constexpr const std::uint32_t worker_threads = 2;
1843+
1844+ // create returns a Runtime instance with pool_size worker threads
1845+ // executing the underlying service.
1846+ static std::shared_ptr<Runtime> create(std::uint32_t pool_size = worker_threads);
1847+
1848+ Runtime(const Runtime&) = delete;
1849+ Runtime(Runtime&&) = delete;
1850+ // Tears down the runtime, stopping all worker threads.
1851+ ~Runtime() noexcept(true);
1852+ Runtime& operator=(const Runtime&) = delete;
1853+ Runtime& operator=(Runtime&&) = delete;
1854+
1855+ // start executes the underlying io_service on a thread pool with
1856+ // the size configured at creation time.
1857+ void start();
1858+
1859+ // stop cleanly shuts down a Runtime instance,
1860+ // joining all worker threads.
1861+ void stop();
1862+
1863+ // to_dispatcher_functional returns a function for integration
1864+ // with components that expect a dispatcher for operation.
1865+ std::function<void(std::function<void()>)> to_dispatcher_functional();
1866+
1867+ // service returns the underlying boost::asio::io_service that is executed
1868+ // by the Runtime.
1869+ boost::asio::io_service& service();
1870+
1871+private:
1872+ // Runtime constructs a new instance, firing up pool_size
1873+ // worker threads.
1874+ Runtime(std::uint32_t pool_size);
1875+
1876+ std::uint32_t pool_size_;
1877+ boost::asio::io_service service_;
1878+ boost::asio::io_service::strand strand_;
1879+ boost::asio::io_service::work keep_alive_;
1880+ std::vector<std::thread> workers_;
1881+};
1882+}
1883+}
1884+}
1885+}
1886+
1887+#endif // COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_
1888
1889=== modified file 'src/location_service/com/ubuntu/location/service/session/skeleton.cpp'
1890--- src/location_service/com/ubuntu/location/service/session/skeleton.cpp 2014-08-14 20:31:09 +0000
1891+++ src/location_service/com/ubuntu/location/service/session/skeleton.cpp 2016-01-13 12:31:53 +0000
1892@@ -283,7 +283,13 @@
1893 VLOG(10) << __PRETTY_FUNCTION__;
1894 try
1895 {
1896- configuration.remote.object->invoke_method_asynchronously<culs::session::Interface::UpdatePosition, void>(position);
1897+ configuration.remote.object->invoke_method_asynchronously_with_callback<culs::session::Interface::UpdatePosition, void>([](const core::dbus::Result<void>& result)
1898+ {
1899+ if (result.is_error())
1900+ {
1901+ LOG(INFO) << "Failed to communicate position update to client: " << result.error().print();
1902+ }
1903+ }, position);
1904 } catch(const std::exception&)
1905 {
1906 // We consider the session to be dead once we hit an exception here.
1907@@ -300,7 +306,13 @@
1908 VLOG(10) << __PRETTY_FUNCTION__;
1909 try
1910 {
1911- configuration.remote.object->invoke_method_asynchronously<culs::session::Interface::UpdateHeading, void>(heading);
1912+ configuration.remote.object->invoke_method_asynchronously_with_callback<culs::session::Interface::UpdateHeading, void>([](const core::dbus::Result<void>& result)
1913+ {
1914+ if (result.is_error())
1915+ {
1916+ LOG(INFO) << "Failed to communicate position update to client: " << result.error().print();
1917+ }
1918+ }, heading);
1919 } catch(const std::exception&)
1920 {
1921 // We consider the session to be dead once we hit an exception here.
1922@@ -317,7 +329,13 @@
1923 VLOG(10) << __PRETTY_FUNCTION__;
1924 try
1925 {
1926- configuration.remote.object->invoke_method_asynchronously<culs::session::Interface::UpdateVelocity, void>(velocity);
1927+ configuration.remote.object->invoke_method_asynchronously_with_callback<culs::session::Interface::UpdateVelocity, void>([](const core::dbus::Result<void>& result)
1928+ {
1929+ if (result.is_error())
1930+ {
1931+ LOG(INFO) << "Failed to communicate position update to client: " << result.error().print();
1932+ }
1933+ }, velocity);
1934 } catch(const std::exception&)
1935 {
1936 // We consider the session to be dead once we hit an exception here.
1937
1938=== modified file 'src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp'
1939--- src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp 2014-09-19 14:36:51 +0000
1940+++ src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp 2016-01-13 12:31:53 +0000
1941@@ -146,7 +146,7 @@
1942 return service::PermissionManager::Result::rejected;
1943 }
1944
1945- std::string description = i18n::tr("%1% wants to access your current location.");
1946+ std::string description = i18n::tr("wants to access your current location.");
1947
1948 core::trust::Agent::RequestParameters params
1949 {
1950
1951=== modified file 'src/location_service/com/ubuntu/location/time_based_update_policy.cpp'
1952--- src/location_service/com/ubuntu/location/time_based_update_policy.cpp 2015-04-23 21:30:04 +0000
1953+++ src/location_service/com/ubuntu/location/time_based_update_policy.cpp 2016-01-13 12:31:53 +0000
1954@@ -53,8 +53,9 @@
1955 {
1956 // if the update has happened within a reasonable amount of time we will just use it if it is more accurate
1957 // that the previous one.
1958- use_new_update = last_position_update.value.accuracy.horizontal && update.value.accuracy.horizontal
1959- && *last_position_update.value.accuracy.horizontal >= *update.value.accuracy.horizontal;
1960+ use_new_update = !last_position_update.value.accuracy.horizontal ||
1961+ (update.value.accuracy.horizontal
1962+ && *last_position_update.value.accuracy.horizontal >= *update.value.accuracy.horizontal);
1963 }
1964
1965 if (use_new_update)
1966@@ -118,4 +119,4 @@
1967
1968 }
1969 }
1970-}
1971\ No newline at end of file
1972+}
1973
1974=== modified file 'tests/CMakeLists.txt'
1975--- tests/CMakeLists.txt 2015-04-23 17:04:09 +0000
1976+++ tests/CMakeLists.txt 2016-01-13 12:31:53 +0000
1977@@ -92,6 +92,7 @@
1978 LOCATION_SERVICE_ADD_TEST(provider_test provider_test.cpp)
1979 LOCATION_SERVICE_ADD_TEST(wgs84_test wgs84_test.cpp)
1980 LOCATION_SERVICE_ADD_TEST(trust_store_permission_manager_test trust_store_permission_manager_test.cpp)
1981+LOCATION_SERVICE_ADD_TEST(runtime_test runtime_test.cpp)
1982
1983 # Provider-specific test-cases go here.
1984 if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
1985@@ -124,3 +125,4 @@
1986
1987 LOCATION_SERVICE_ADD_TEST(remote_provider_test remote_provider_test.cpp)
1988 LOCATION_SERVICE_ADD_TEST(espoo_provider_test espoo_provider_test.cpp)
1989+LOCATION_SERVICE_ADD_TEST(delayed_service_test delayed_service_test.cpp)
1990
1991=== modified file 'tests/acceptance_tests.cpp'
1992--- tests/acceptance_tests.cpp 2015-02-13 13:19:18 +0000
1993+++ tests/acceptance_tests.cpp 2016-01-13 12:31:53 +0000
1994@@ -38,12 +38,14 @@
1995 #include <com/ubuntu/location/service/stub.h>
1996
1997 #include <core/dbus/announcer.h>
1998+#include <core/dbus/bus.h>
1999 #include <core/dbus/fixture.h>
2000 #include <core/dbus/resolver.h>
2001
2002 #include <core/dbus/asio/executor.h>
2003
2004 #include <core/posix/signal.h>
2005+#include <core/posix/this_process.h>
2006
2007 #include <core/testing/cross_process_sync.h>
2008 #include <core/testing/fork_and_run.h>
2009@@ -663,6 +665,110 @@
2010 EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(server, client));
2011 }
2012
2013+TEST_F(LocationServiceStandalone, NewSessionsGetLastKnownPosition)
2014+{
2015+ core::testing::CrossProcessSync sync_start;
2016+
2017+ auto server = [this, &sync_start]()
2018+ {
2019+ SCOPED_TRACE("Server");
2020+
2021+ auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term});
2022+ trap->signal_raised().connect([trap](core::posix::Signal)
2023+ {
2024+ trap->stop();
2025+ });
2026+
2027+ auto incoming = session_bus();
2028+ auto outgoing = session_bus();
2029+
2030+ incoming->install_executor(core::dbus::asio::make_executor(incoming));
2031+ outgoing->install_executor(core::dbus::asio::make_executor(outgoing));
2032+
2033+ auto dummy = new DummyProvider();
2034+ cul::Provider::Ptr helper(dummy);
2035+
2036+ cul::service::DefaultConfiguration config;
2037+ cul::service::Implementation::Configuration configuration
2038+ {
2039+ incoming,
2040+ outgoing,
2041+ config.the_engine(config.the_provider_set(helper), config.the_provider_selection_policy(), null_settings()),
2042+ config.the_permission_manager(incoming),
2043+ cul::service::Harvester::Configuration
2044+ {
2045+ cul::connectivity::platform_default_manager(),
2046+ std::make_shared<NullReporter>()
2047+ }
2048+ };
2049+ auto location_service = std::make_shared<cul::service::Implementation>(configuration);
2050+
2051+ configuration.engine->updates.last_known_location.set(reference_position_update);
2052+ std::thread t1{[incoming](){incoming->run();}};
2053+ std::thread t2{[outgoing](){outgoing->run();}};
2054+
2055+ sync_start.try_signal_ready_for(std::chrono::milliseconds{500});
2056+
2057+ trap->run();
2058+
2059+ incoming->stop();
2060+ outgoing->stop();
2061+
2062+ if (t1.joinable())
2063+ t1.join();
2064+
2065+ if (t2.joinable())
2066+ t2.join();
2067+
2068+ return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
2069+ };
2070+
2071+ auto client = [this, &sync_start]()
2072+ {
2073+ SCOPED_TRACE("Client");
2074+
2075+ EXPECT_EQ(1, sync_start.wait_for_signal_ready_for(std::chrono::milliseconds{500}));
2076+
2077+ auto bus = session_bus();
2078+ bus->install_executor(dbus::asio::make_executor(bus));
2079+ std::thread t{[bus](){bus->run();}};
2080+
2081+ auto location_service = dbus::resolve_service_on_bus<
2082+ cul::service::Interface,
2083+ cul::service::Stub>(bus);
2084+
2085+ auto s1 = location_service->create_session_for_criteria(cul::Criteria{});
2086+
2087+ std::cout << "Successfully created session" << std::endl;
2088+
2089+ cul::Update<cul::Position> position;
2090+ auto c1 = s1->updates().position.changed().connect(
2091+ [&](const cul::Update<cul::Position>& new_position) {
2092+ std::cout << "On position updated: " << new_position << std::endl;
2093+ position = new_position;
2094+ });
2095+
2096+ std::cout << "Created event connections, starting updates..." << std::endl;
2097+
2098+ s1->updates().position_status = culss::Interface::Updates::Status::enabled;
2099+
2100+ std::cout << "done" << std::endl;
2101+
2102+ std::this_thread::sleep_for(std::chrono::milliseconds{1000});
2103+
2104+ bus->stop();
2105+
2106+ if (t.joinable())
2107+ t.join();
2108+
2109+ EXPECT_EQ(reference_position_update, position);
2110+
2111+ return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
2112+ };
2113+
2114+ EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(server, client));
2115+}
2116+
2117 namespace
2118 {
2119 struct LocationServiceStandaloneLoad : public LocationServiceStandalone
2120@@ -708,7 +814,7 @@
2121
2122 options.add(Keys::update_period,
2123 "Update period length for dummy::Provider setup.",
2124- std::uint32_t{100});
2125+ std::uint32_t{10});
2126
2127 options.add(Keys::client_count,
2128 "Number of clients that should be fired up.",
2129@@ -761,6 +867,8 @@
2130 };
2131 }
2132
2133+#include "did_finish_successfully.h"
2134+
2135 TEST_F(LocationServiceStandaloneLoad, MultipleClientsConnectingAndDisconnectingWorks)
2136 {
2137 EXPECT_TRUE(trust_store_is_set_up_for_testing);
2138@@ -801,8 +909,8 @@
2139 };
2140
2141 cul::service::Daemon::Configuration config;
2142- config.incoming = session_bus();
2143- config.outgoing = session_bus();
2144+ config.incoming = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS"));
2145+ config.outgoing = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS"));
2146 config.is_testing_enabled = false;
2147 config.providers =
2148 {
2149@@ -829,7 +937,7 @@
2150 status;
2151 }, core::posix::StandardStream::empty);
2152
2153- std::this_thread::sleep_for(std::chrono::seconds{2});
2154+ std::this_thread::sleep_for(std::chrono::seconds{15});
2155
2156 auto client = [this]()
2157 {
2158@@ -957,17 +1065,11 @@
2159 {
2160 VLOG(1) << "Stopping client...: " << client.pid();
2161 client.send_signal_or_throw(core::posix::Signal::sig_term);
2162- auto result = client.wait_for(core::posix::wait::Flags::untraced);
2163-
2164- EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status);
2165- EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status);
2166+ EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced)));
2167 }
2168
2169 VLOG(1) << "Cleaned up clients, shutting down the service...";
2170
2171 server.send_signal_or_throw(core::posix::Signal::sig_term);
2172- auto result = server.wait_for(core::posix::wait::Flags::untraced);
2173-
2174- EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status);
2175- EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status);
2176+ EXPECT_TRUE(did_finish_successfully(server.wait_for(core::posix::wait::Flags::untraced)));
2177 }
2178
2179=== added file 'tests/delayed_service_test.cpp'
2180--- tests/delayed_service_test.cpp 1970-01-01 00:00:00 +0000
2181+++ tests/delayed_service_test.cpp 2016-01-13 12:31:53 +0000
2182@@ -0,0 +1,193 @@
2183+/*
2184+ * Copyright © 2014 Canonical Ltd.
2185+ *
2186+ * This program is free software: you can redistribute it and/or modify it
2187+ * under the terms of the GNU Lesser General Public License version 3,
2188+ * as published by the Free Software Foundation.
2189+ *
2190+ * This program is distributed in the hope that it will be useful,
2191+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2192+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2193+ * GNU Lesser General Public License for more details.
2194+ *
2195+ * You should have received a copy of the GNU Lesser General Public License
2196+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2197+ *
2198+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2199+ * Scott Sweeny <scott.sweeny@canonical.com>
2200+ */
2201+
2202+#include <com/ubuntu/location/service/daemon.h>
2203+#include <com/ubuntu/location/service/provider_daemon.h>
2204+#include <com/ubuntu/location/providers/remote/provider.h>
2205+
2206+#include <com/ubuntu/location/service/stub.h>
2207+
2208+#include <com/ubuntu/location/position.h>
2209+#include <com/ubuntu/location/update.h>
2210+
2211+#include <core/dbus/fixture.h>
2212+
2213+#include <core/dbus/asio/executor.h>
2214+
2215+#include <core/posix/fork.h>
2216+#include <core/posix/signal.h>
2217+#include <core/posix/this_process.h>
2218+
2219+#include "did_finish_successfully.h"
2220+#include "mock_event_receiver.h"
2221+
2222+#include <gmock/gmock.h>
2223+
2224+namespace location = com::ubuntu::location;
2225+namespace remote = com::ubuntu::location::providers::remote;
2226+
2227+namespace
2228+{
2229+struct DelayedServiceTest : public core::dbus::testing::Fixture, public ::testing::WithParamInterface<int>
2230+{
2231+
2232+};
2233+}
2234+
2235+TEST_P(DelayedServiceTest, AClientReceivesUpdatesFromADelayedProvider)
2236+{
2237+ auto oopp = core::posix::fork([this]()
2238+ {
2239+ auto bus = session_bus();
2240+
2241+ // Pass the delay value to the provider
2242+ char delay[50];
2243+ sprintf(delay, "--dummy::DelayedProvider::DelayInMs=%d", GetParam());
2244+
2245+ const char* argv[] =
2246+ {
2247+ "--bus", "session", // 2
2248+ "--service-name", "com.ubuntu.location.providers.Dummy", // 4
2249+ "--service-path", "/com/ubuntu/location/providers/Dummy", // 6
2250+ "--provider", "dummy::DelayedProvider", // 8
2251+ delay // 9
2252+ };
2253+
2254+ auto dbus_connection_factory = [bus](core::dbus::WellKnownBus)
2255+ {
2256+ return bus;
2257+ };
2258+
2259+ return static_cast<core::posix::exit::Status>(
2260+ location::service::ProviderDaemon::main(
2261+ location::service::ProviderDaemon::Configuration::from_command_line_args(
2262+ 9, argv, dbus_connection_factory)));
2263+ }, core::posix::StandardStream::empty);
2264+
2265+ std::this_thread::sleep_for(std::chrono::milliseconds{250});
2266+
2267+ auto service = core::posix::fork([this]()
2268+ {
2269+ core::posix::this_process::env::set_or_throw(
2270+ "TRUST_STORE_PERMISSION_MANAGER_IS_RUNNING_UNDER_TESTING",
2271+ "1");
2272+
2273+ const char* argv[] =
2274+ {
2275+ "--bus", "session", // 2
2276+ "--provider", "remote::Provider", // 4
2277+ "--remote::Provider::bus=session_with_address_from_env", // 5
2278+ "--remote::Provider::name=com.ubuntu.location.providers.Dummy", // 6
2279+ "--remote::Provider::path=/com/ubuntu/location/providers/Dummy" // 7
2280+ };
2281+
2282+ // The daemon instance requires two bus instances.
2283+ auto dbus_connection_factory = [this](core::dbus::WellKnownBus)
2284+ {
2285+ return session_bus();
2286+ };
2287+
2288+ return static_cast<core::posix::exit::Status>(
2289+ location::service::Daemon::main(
2290+ location::service::Daemon::Configuration::from_command_line_args(
2291+ 7, argv, dbus_connection_factory)));
2292+ }, core::posix::StandardStream::empty);
2293+
2294+ // Wait to setup the client until the service is up
2295+ std::this_thread::sleep_for(std::chrono::milliseconds{250 + GetParam()});
2296+
2297+ auto client = core::posix::fork([this]()
2298+ {
2299+ using namespace ::testing;
2300+
2301+ auto trap = core::posix::trap_signals_for_all_subsequent_threads(
2302+ {
2303+ core::posix::Signal::sig_term,
2304+ core::posix::Signal::sig_int
2305+ });
2306+
2307+ trap->signal_raised().connect([trap](const core::posix::Signal&)
2308+ {
2309+ trap->stop();
2310+ });
2311+
2312+ auto bus = session_bus();
2313+ bus->install_executor(core::dbus::asio::make_executor(bus));
2314+
2315+ std::thread worker
2316+ {
2317+ [bus]() { bus->run(); }
2318+ };
2319+
2320+ MockEventReceiver receiver;
2321+ EXPECT_CALL(receiver, position_update_received(_)).Times(AtLeast(1));
2322+ EXPECT_CALL(receiver, heading_update_received(_)).Times(AtLeast(1));
2323+ EXPECT_CALL(receiver, velocity_update_received(_)).Times(AtLeast(1));
2324+
2325+ com::ubuntu::location::service::Stub service{bus};
2326+
2327+ auto session = service.create_session_for_criteria(location::Criteria{});
2328+
2329+ session->updates().position.changed().connect([&receiver](location::Update<location::Position> pos)
2330+ {
2331+ receiver.position_update_received(pos);
2332+ });
2333+
2334+ session->updates().heading.changed().connect([&receiver](location::Update<location::Heading> heading)
2335+ {
2336+ receiver.heading_update_received(heading);
2337+ });
2338+
2339+ session->updates().velocity.changed().connect([&receiver](location::Update<location::Velocity> velocity)
2340+ {
2341+ receiver.velocity_update_received(velocity);
2342+ });
2343+
2344+ session->updates().position_status = location::service::session::Interface::Updates::Status::enabled;
2345+ session->updates().velocity_status = location::service::session::Interface::Updates::Status::enabled;
2346+ session->updates().heading_status = location::service::session::Interface::Updates::Status::enabled;
2347+
2348+ trap->run();
2349+
2350+ bus->stop();
2351+
2352+ if (worker.joinable())
2353+ worker.join();
2354+
2355+ return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure :
2356+ core::posix::exit::Status::success;
2357+ }, core::posix::StandardStream::empty);
2358+
2359+ std::this_thread::sleep_for(std::chrono::milliseconds{4000});
2360+
2361+ std::cout << "Shutting down client" << std::endl;
2362+ client.send_signal_or_throw(core::posix::Signal::sig_term);
2363+ EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced)));
2364+
2365+ std::cout << "Shutting down service" << std::endl;
2366+ service.send_signal_or_throw(core::posix::Signal::sig_term);
2367+ EXPECT_TRUE(did_finish_successfully(service.wait_for(core::posix::wait::Flags::untraced)));
2368+
2369+ std::cout << "Shutting down oopp" << std::endl;
2370+ oopp.send_signal_or_throw(core::posix::Signal::sig_term);
2371+ EXPECT_TRUE(did_finish_successfully(oopp.wait_for(core::posix::wait::Flags::untraced)));
2372+}
2373+
2374+INSTANTIATE_TEST_CASE_P(ServiceDelays, DelayedServiceTest,
2375+ ::testing::Values(0, 250, 500, 1000, 2000, 5000, 10000));
2376
2377=== modified file 'tests/engine_test.cpp'
2378--- tests/engine_test.cpp 2015-01-21 20:04:56 +0000
2379+++ tests/engine_test.cpp 2016-01-13 12:31:53 +0000
2380@@ -154,9 +154,9 @@
2381 EXPECT_CALL(*provider, on_reference_velocity_updated(_)).Times(1);
2382
2383 engine.configuration.wifi_and_cell_id_reporting_state = location::WifiAndCellIdReportingState::on;
2384- engine.updates.reference_location = location::Update<location::Position>{};
2385- engine.updates.reference_heading = location::Update<location::Heading>{};
2386- engine.updates.reference_velocity = location::Update<location::Velocity>{};
2387+ engine.updates.last_known_location = location::Update<location::Position>{};
2388+ engine.updates.last_known_heading = location::Update<location::Heading>{};
2389+ engine.updates.last_known_velocity = location::Update<location::Velocity>{};
2390 }
2391
2392 /* TODO(tvoss): We have to disable these tests as the MP is being refactored to not break ABI.
2393
2394=== modified file 'tests/gps_provider_test.cpp'
2395--- tests/gps_provider_test.cpp 2015-01-12 08:41:14 +0000
2396+++ tests/gps_provider_test.cpp 2016-01-13 12:31:53 +0000
2397@@ -48,6 +48,31 @@
2398
2399 namespace
2400 {
2401+
2402+struct MockHardwareGps
2403+{
2404+ MockHardwareGps()
2405+ {
2406+ instance_ = this;
2407+ }
2408+ ~MockHardwareGps()
2409+ {
2410+ instance_ = nullptr;
2411+ }
2412+
2413+ MOCK_METHOD5(set_position_mode, bool(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t));
2414+ MOCK_METHOD3(inject_time, void(int64_t, int64_t, int));
2415+
2416+ static MockHardwareGps *mocked(UHardwareGps self) {
2417+ return reinterpret_cast<MockHardwareGps*>(self);
2418+ }
2419+ static MockHardwareGps *instance() { return instance_; }
2420+
2421+ static MockHardwareGps *instance_;
2422+};
2423+
2424+MockHardwareGps *MockHardwareGps::instance_ = nullptr;
2425+
2426 struct UpdateTrap
2427 {
2428 MOCK_METHOD1(on_position_updated, void(const location::Position&));
2429@@ -211,6 +236,42 @@
2430
2431 }
2432
2433+/* Mock the hardware GPS platform API: the methods defined here will be invoked
2434+ * instead of those exported by the system library.
2435+ * We redefine these methods using the MockHardwareGps class above, which is
2436+ * implemented using google-mock. This effectively allows us to test that the
2437+ * right calls to the platform API are made.
2438+ */
2439+UHardwareGps
2440+u_hardware_gps_new(UHardwareGpsParams *)
2441+{
2442+ using namespace ::testing;
2443+
2444+ return reinterpret_cast<UHardwareGps>(MockHardwareGps::instance());
2445+}
2446+
2447+void
2448+u_hardware_gps_delete(UHardwareGps)
2449+{
2450+}
2451+
2452+bool
2453+u_hardware_gps_set_position_mode(UHardwareGps self, uint32_t mode, uint32_t recurrence,
2454+ uint32_t min_interval, uint32_t preferred_accuracy,
2455+ uint32_t preferred_time)
2456+{
2457+ MockHardwareGps *thiz = MockHardwareGps::mocked(self);
2458+ return thiz->set_position_mode(mode, recurrence, min_interval,
2459+ preferred_accuracy, preferred_time);
2460+}
2461+
2462+void
2463+u_hardware_gps_inject_time(UHardwareGps self, int64_t time, int64_t time_reference, int uncertainty)
2464+{
2465+ MockHardwareGps* thiz = MockHardwareGps::mocked(self);
2466+ return thiz->inject_time(time, time_reference, uncertainty);
2467+}
2468+
2469 TEST(AndroidGpsXtraDownloader, reading_configuration_from_valid_conf_file_works)
2470 {
2471 std::stringstream ss{gps_conf};
2472@@ -261,6 +322,28 @@
2473 provider.on_reference_location_updated(pos);
2474 }
2475
2476+TEST(GpsProvider, time_requests_inject_current_time_into_the_hal)
2477+{
2478+ using namespace ::testing;
2479+
2480+ NiceMock<MockHardwareGps> hardwareGps;
2481+
2482+ gps::android::HardwareAbstractionLayer::Configuration configuration;
2483+ gps::android::HardwareAbstractionLayer hal(configuration);
2484+ std::shared_ptr<gps::HardwareAbstractionLayer> hal_ptr(&hal, [](gps::HardwareAbstractionLayer*){});
2485+
2486+ gps::Provider provider(hal_ptr);
2487+ int64_t time = 0;
2488+ EXPECT_CALL(hardwareGps, inject_time(_, _, 0)).Times(1).WillOnce(SaveArg<0>(&time));
2489+
2490+ auto t0 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());
2491+
2492+ gps::android::HardwareAbstractionLayer::on_request_utc_time(&hal);
2493+
2494+ auto t1 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());
2495+ EXPECT_THAT(time, AllOf(Ge(t0.count()), Le(t1.count())));
2496+}
2497+
2498 TEST(GpsProvider, updates_from_hal_are_passed_on_by_the_provider)
2499 {
2500 using namespace ::testing;
2501
2502=== added file 'tests/mock_event_receiver.h'
2503--- tests/mock_event_receiver.h 1970-01-01 00:00:00 +0000
2504+++ tests/mock_event_receiver.h 2016-01-13 12:31:53 +0000
2505@@ -0,0 +1,35 @@
2506+/*
2507+ * Copyright © 2015 Canonical Ltd.
2508+ *
2509+ * This program is free software: you can redistribute it and/or modify it
2510+ * under the terms of the GNU Lesser General Public License version 3,
2511+ * as published by the Free Software Foundation.
2512+ *
2513+ * This program is distributed in the hope that it will be useful,
2514+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2515+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2516+ * GNU Lesser General Public License for more details.
2517+ *
2518+ * You should have received a copy of the GNU Lesser General Public License
2519+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2520+ *
2521+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2522+ * Scott Sweeny <scott.sweeny@canonical.com>
2523+ */
2524+#ifndef MOCK_EVENT_RECEIVER_H_
2525+#define MOCK_EVENT_RECEIVER_H_
2526+
2527+#include <com/ubuntu/location/update.h>
2528+
2529+#include <gmock/gmock.h>
2530+
2531+namespace location = com::ubuntu::location;
2532+
2533+struct MockEventReceiver
2534+{
2535+ MOCK_METHOD1(position_update_received, void(const location::Update<location::Position>&));
2536+ MOCK_METHOD1(heading_update_received, void(const location::Update<location::Heading>&));
2537+ MOCK_METHOD1(velocity_update_received, void(const location::Update<location::Velocity>&));
2538+};
2539+
2540+#endif // MOCK_EVENT_RECEIVER_H_
2541
2542=== modified file 'tests/position_test.cpp'
2543--- tests/position_test.cpp 2014-06-20 07:40:34 +0000
2544+++ tests/position_test.cpp 2016-01-13 12:31:53 +0000
2545@@ -40,7 +40,7 @@
2546 cul::wgs84::Latitude{},
2547 cul::wgs84::Longitude{},
2548 cul::wgs84::Altitude{}};
2549- EXPECT_TRUE(p.altitude);
2550+ EXPECT_TRUE(p.altitude ? true : false);
2551 }
2552
2553 #include <com/ubuntu/location/codec.h>
2554
2555=== modified file 'tests/remote_providerd_test.cpp'
2556--- tests/remote_providerd_test.cpp 2014-10-27 21:58:16 +0000
2557+++ tests/remote_providerd_test.cpp 2016-01-13 12:31:53 +0000
2558@@ -31,6 +31,7 @@
2559 #include <core/posix/fork.h>
2560
2561 #include "did_finish_successfully.h"
2562+#include "mock_event_receiver.h"
2563
2564 #include <gmock/gmock.h>
2565
2566@@ -38,13 +39,6 @@
2567
2568 namespace
2569 {
2570-struct MockEventReceiver
2571-{
2572- MOCK_METHOD1(position_update_received, void(const location::Update<location::Position>&));
2573- MOCK_METHOD1(heading_update_received, void(const location::Update<location::Heading>&));
2574- MOCK_METHOD1(velocity_update_received, void(const location::Update<location::Velocity>&));
2575-};
2576-
2577 struct RemoteProviderdTest : public core::dbus::testing::Fixture
2578 {
2579
2580
2581=== added file 'tests/runtime_test.cpp'
2582--- tests/runtime_test.cpp 1970-01-01 00:00:00 +0000
2583+++ tests/runtime_test.cpp 2016-01-13 12:31:53 +0000
2584@@ -0,0 +1,118 @@
2585+/*
2586+ * Copyright © 2015Canonical Ltd.
2587+ *
2588+ * This program is free software: you can redistribute it and/or modify it
2589+ * under the terms of the GNU Lesser General Public License version 3,
2590+ * as published by the Free Software Foundation.
2591+ *
2592+ * This program is distributed in the hope that it will be useful,
2593+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2594+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2595+ * GNU Lesser General Public License for more details.
2596+ *
2597+ * You should have received a copy of the GNU Lesser General Public License
2598+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2599+ *
2600+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2601+ */
2602+#include <com/ubuntu/location/service/runtime.h>
2603+
2604+#include <gtest/gtest.h>
2605+
2606+#include <condition_variable>
2607+#include <thread>
2608+
2609+namespace culs = com::ubuntu::location::service;
2610+
2611+TEST(Runtime, cleanly_shuts_down_threads)
2612+{
2613+ culs::Runtime::create();
2614+}
2615+
2616+TEST(Runtime, executes_service)
2617+{
2618+ std::mutex m;
2619+ std::unique_lock<std::mutex> ul{m};
2620+ std::condition_variable wc;
2621+
2622+ bool signaled = false;
2623+
2624+ auto rt = culs::Runtime::create();
2625+ rt->start();
2626+ boost::asio::deadline_timer timer{rt->service(), boost::posix_time::milliseconds(500)};
2627+ timer.async_wait([&wc, &signaled](const boost::system::error_code&)
2628+ {
2629+ signaled = true;
2630+ wc.notify_all();
2631+ });
2632+
2633+ auto result = wc.wait_for(ul, std::chrono::seconds{1}, [&signaled]() { return signaled; });
2634+ EXPECT_TRUE(result);
2635+}
2636+
2637+TEST(Runtime, catches_exceptions_thrown_from_handlers)
2638+{
2639+ std::mutex m;
2640+ std::unique_lock<std::mutex> ul{m};
2641+ std::condition_variable wc;
2642+
2643+ bool signaled = false;
2644+
2645+ auto rt = culs::Runtime::create();
2646+ rt->start();
2647+ boost::asio::deadline_timer fast{rt->service(), boost::posix_time::milliseconds(100)};
2648+ fast.async_wait([](const boost::system::error_code&)
2649+ {
2650+ throw std::runtime_error{"Should not propagate"};
2651+ });
2652+
2653+ boost::asio::deadline_timer slow{rt->service(), boost::posix_time::milliseconds(500)};
2654+ slow.async_wait([&wc, &signaled](const boost::system::error_code&)
2655+ {
2656+ signaled = true;
2657+ wc.notify_all();
2658+ });
2659+
2660+ auto result = wc.wait_for(ul, std::chrono::seconds{1}, [&signaled]() { return signaled; });
2661+ EXPECT_TRUE(result);
2662+}
2663+
2664+// sets_up_pool_of_threads ensures that the pool size
2665+// passed to the Runtime on construction is honored. The idea is simple:
2666+// We set up two deadline timers, fast and slow. fast fires before slow,
2667+// with fast blocking in a wait on a common condition_variable. When slow
2668+// fires, it notifies the condition variable, thereby unblocking the handler of fast,
2669+// enabling clean shutdown without errors and timeouts. This only works if the
2670+// pool contains at least 2 threads. Otherwise, the handler of slow would not be executed
2671+// until the handler of fast times out in the wait, marking the test as failed.
2672+TEST(Runtime, sets_up_pool_of_threads)
2673+{
2674+ struct State
2675+ {
2676+ bool signaled{false};
2677+ std::mutex m;
2678+ std::condition_variable wc;
2679+ };
2680+
2681+ auto state = std::make_shared<State>();
2682+
2683+ auto rt = culs::Runtime::create(2);
2684+ rt->start();
2685+ boost::asio::deadline_timer fast{rt->service(), boost::posix_time::milliseconds(100)};
2686+ fast.async_wait([state](const boost::system::error_code&)
2687+ {
2688+ std::unique_lock<std::mutex> ul{state->m};
2689+ EXPECT_TRUE(state->wc.wait_for(ul, std::chrono::seconds{1}, [state]() { return state->signaled; }));
2690+ });
2691+
2692+ boost::asio::deadline_timer slow{rt->service(), boost::posix_time::milliseconds(500)};
2693+ slow.async_wait([state](const boost::system::error_code&)
2694+ {
2695+ state->signaled = true;
2696+ state->wc.notify_all();
2697+ });
2698+
2699+ std::unique_lock<std::mutex> ul{state->m};
2700+ auto result = state->wc.wait_for(ul, std::chrono::seconds{1}, [state]() { return state->signaled; });
2701+ EXPECT_TRUE(result);
2702+}
2703
2704=== added directory 'tools'
2705=== added file 'tools/CMakeLists.txt'
2706--- tools/CMakeLists.txt 1970-01-01 00:00:00 +0000
2707+++ tools/CMakeLists.txt 2016-01-13 12:31:53 +0000
2708@@ -0,0 +1,1 @@
2709+configure_file(symbol_diff.in symbol_diff)
2710
2711=== added file 'tools/symbol_diff.in'
2712--- tools/symbol_diff.in 1970-01-01 00:00:00 +0000
2713+++ tools/symbol_diff.in 2016-01-13 12:31:53 +0000
2714@@ -0,0 +1,70 @@
2715+#! /usr/bin/env python3
2716+
2717+#
2718+# Copyright (C) 2014 Canonical Ltd
2719+#
2720+# This program is free software: you can redistribute it and/or modify
2721+# it under the terms of the GNU Lesser General Public License version 3 as
2722+# published by the Free Software Foundation.
2723+#
2724+# This program is distributed in the hope that it will be useful,
2725+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2726+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2727+# GNU Lesser General Public License for more details.
2728+#
2729+# You should have received a copy of the GNU Lesser General Public License
2730+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2731+#
2732+# Authored by: Michi Henning <michi.henning@canonical.com>
2733+#
2734+
2735+import re
2736+import subprocess
2737+
2738+OLD_FILE = './debian/libubuntu-location-service@UBUNTU_LOCATION_SERVICE_VERSION_MAJOR@.symbols'
2739+NEW_FILE = './debian/libubuntu-location-service@UBUNTU_LOCATION_SERVICE_VERSION_MAJOR@/DEBIAN/symbols'
2740+
2741+def run():
2742+ old_regex = re.compile(r'^ (\(.*\))"(.*)" (.*)$')
2743+
2744+ old_syms = {} # Dictionary containing symbol -> ( tag, version )
2745+ with open(OLD_FILE, encoding='utf=8') as file:
2746+ file.readline() # Skip first line, which is the library name and version
2747+ for line in file:
2748+ mo = old_regex.match(line)
2749+ if mo:
2750+ old_syms[mo.group(2)] = ( mo.group(1), mo.group(3) )
2751+ else:
2752+ raise Exception('Invalid input line in ' + OLD_FILE + ': ' + line)
2753+
2754+ new_regex = re.compile(r'^ (.*) .+$')
2755+
2756+ # Run the new symbols file through "c++filt | sort | uniq". We need
2757+ # the sort | uniq because, otherwise, we end up with duplicate demangled symbols.
2758+ with open(NEW_FILE) as infile, open('new_symbols', 'w') as outfile:
2759+ p = subprocess.Popen(['c++filt | sort | uniq'], shell=True, stdin=infile, stdout=subprocess.PIPE)
2760+
2761+ # For each symbol, if it is in the old dictionary, output the tags from the original
2762+ # symbol file, followed by the symbol and version. Otherwise, use "(c++)" as the tag
2763+ # and add " 0replaceme", so the new symbol will be accepted.
2764+ line = p.stdout.readline().decode('utf-8')
2765+ outfile.write(line) # Write library name and version
2766+ for line in p.stdout:
2767+ mo = new_regex.match(line.decode('utf-8'))
2768+ if (mo):
2769+ sym = mo.group(1)
2770+ try:
2771+ tag, version = old_syms[sym]
2772+ except KeyError:
2773+ tag = '(c++)'
2774+ version = '0replaceme'
2775+ outfile.write(' {}"{}" {}\n'.format(tag, sym, version))
2776+ else:
2777+ raise Exception('Cannot parse demangled line: ' + line)
2778+
2779+ # Write the diff into /tmp/symbols.diff
2780+ with open('/tmp/symbols.diff', 'w') as outfile:
2781+ subprocess.call(['diff', '-u', OLD_FILE, 'new_symbols'], stdout=outfile)
2782+
2783+if __name__ == '__main__':
2784+ run()

Subscribers

People subscribed via source and target branches