[Merge] lp:~thomas-voss/location-service/add_controller_and_service_configuration into lp:location-service

Manuel de la Peña manuel.delapena at canonical.com
Wed Jun 25 15:12:53 UTC 2014


Review: Approve

Looks good and it have been tested IRL. The comments are not blockers.

Diff comments:

> === modified file 'CMakeLists.txt'
> --- CMakeLists.txt	2014-05-05 09:14:35 +0000
> +++ CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -2,12 +2,12 @@
>  
>  project(ubuntu-location-service)
>  
> -set(UBUNTU_LOCATION_SERVICE_VERSION_MAJOR 0)
> +set(UBUNTU_LOCATION_SERVICE_VERSION_MAJOR 1)
>  set(UBUNTU_LOCATION_SERVICE_VERSION_MINOR 0)
> -set(UBUNTU_LOCATION_SERVICE_VERSION_PATCH 3)
> +set(UBUNTU_LOCATION_SERVICE_VERSION_PATCH 0)
>  
> -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wextra -fPIC -pthread")
> -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fno-strict-aliasing -pedantic -Wextra -fPIC -pthread")
> +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wextra -fPIC")
> +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fno-strict-aliasing -pedantic -Wextra -fPIC")
>  
>  set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
>  
> @@ -20,12 +20,17 @@
>  include(GNUInstallDirs)
>  
>  find_package(PkgConfig)
> -find_package(Boost 1.49 COMPONENTS system program_options)
> +find_package(Boost COMPONENTS system program_options)
>  find_package(GLog)
>  find_package(GFlags)
> +find_package(Threads)
>  pkg_check_modules(DBUS dbus-1 REQUIRED)
>  pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED)
> -
> +pkg_check_modules(JSON_CPP jsoncpp REQUIRED)
> +# TODO(tvoss): Re-enable once net-cpp hits the archive.

Shouldn't the TODO comment be removed?

> +pkg_check_modules(NET_CPP net-cpp)
> +pkg_check_modules(PROCESS_CPP process-cpp REQUIRED)
> +pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED)
>  #####################################################################
>  # Enable code coverage calculation with gcov/gcovr/lcov
>  # Usage:
> @@ -43,18 +48,26 @@
>  
>  option (DISABLE_ERROR_ON_LOCAL_TYPEDEFS_WARNINGS "Disable errors when local typedefs are unused" ON)
>  if (DISABLE_ERROR_ON_LOCAL_TYPEDEFS_WARNINGS)
> -	SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-local-typedefs")
> +    SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-local-typedefs")
>  endif (DISABLE_ERROR_ON_LOCAL_TYPEDEFS_WARNINGS)
>  
>  include_directories(
>    ${Boost_INCLUDE_DIRS}
>    ${DBUS_INCLUDE_DIRS}
> -  ${DBUS_CPP_INCLUDE_DIRS}/dbus
> +  ${DBUS_CPP_INCLUDE_DIRS}
> +  ${JSON_CPP_INCLUDE_DIRS}
> +  ${NET_CPP_INCLUDE_DIRS}
> +  ${PROPERTIES_CPP_INCLUDE_DIRS}
> +  ${PROCESS_CPP_INCLUDE_DIRS}
>    ${GLog_INCLUDE_DIR}
>    ${GFlags_INCLUDE_DIR}
> -  include/location_service
> +
> +  ${CMAKE_SOURCE_DIR}/include/location_service
> +  ${CMAKE_SOURCE_DIR}/src/location_service
>  )
>  
> +file(GLOB_RECURSE UBUNTU_LOCATION_SERVICE_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR} *.h)
> +
>  add_subdirectory(data)
>  add_subdirectory(doc)
>  add_subdirectory(examples)
> 
> === modified file 'data/CMakeLists.txt'
> --- data/CMakeLists.txt	2013-08-13 19:52:15 +0000
> +++ data/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -19,12 +19,21 @@
>  )
>  
>  configure_file(
> +  ubuntu-location-service-connectivity.pc.in ubuntu-location-service-connectivity.pc @ONLY
> +)
> +
> +configure_file(
>    ubuntu-location-service.conf.in ubuntu-location-service.conf @ONLY
>  )
>  
>  install(
>    FILES ${CMAKE_CURRENT_BINARY_DIR}/ubuntu-location-service.pc
> -  DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig
> +  DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
> +)
> +
> +install(
> +  FILES ${CMAKE_CURRENT_BINARY_DIR}/ubuntu-location-service-connectivity.pc
> +  DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
>  )
>  
>  install(
> 
> === added file 'data/ubuntu-location-service-connectivity.pc.in'
> --- data/ubuntu-location-service-connectivity.pc.in	1970-01-01 00:00:00 +0000
> +++ data/ubuntu-location-service-connectivity.pc.in	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,12 @@
> +prefix=@CMAKE_INSTALL_PREFIX@
> +exec_prefix=${prefix}
> +libdir=${exec_prefix}/lib
> +includedir=${exec_prefix}/include
> + 
> +Name: ubuntu-location-service-connectivity
> +Description: A location service aggregating position/velocity/heading
> + updates and exporting them over dbus, wifi and cell id query interfaces.
> +Version: @UBUNTU_LOCATION_SERVICE_VERSION_MAJOR at .@UBUNTU_LOCATION_SERVICE_VERSION_MINOR at .@UBUNTU_LOCATION_SERVICE_VERSION_PATCH@
> +Libs: -L${libdir} -lubuntu-location-service-connectivity
> +Cflags: -I${includedir}/ubuntu-location-service- at UBUNTU_LOCATION_SERVICE_VERSION_MAJOR@
> +Requires: dbus-cpp
> 
> === modified file 'data/ubuntu-location-service.pc.in'
> --- data/ubuntu-location-service.pc.in	2013-08-19 05:51:55 +0000
> +++ data/ubuntu-location-service.pc.in	2014-06-24 16:02:38 +0000
> @@ -9,4 +9,4 @@
>  Version: @UBUNTU_LOCATION_SERVICE_VERSION_MAJOR at .@UBUNTU_LOCATION_SERVICE_VERSION_MINOR at .@UBUNTU_LOCATION_SERVICE_VERSION_PATCH@
>  Libs: -L${libdir} -lubuntu-location-service
>  Cflags: -I${includedir}/ubuntu-location-service- at UBUNTU_LOCATION_SERVICE_VERSION_MAJOR@
> -Requires: dbus-cpp
> \ No newline at end of file
> +Requires: dbus-cpp
> 
> === modified file 'debian/changelog'
> --- debian/changelog	2014-06-12 10:45:09 +0000
> +++ debian/changelog	2014-06-24 16:02:38 +0000
> @@ -1,3 +1,9 @@
> +location-service (1.0.0) UNRELEASED; urgency=medium
> +
> +  * Bump major version.
> +
> + -- Thomas Voß <thomas.voss at canonical.com>  Tue, 24 Jun 2014 15:07:04 +0200
> +
>  location-service (0.0.3+14.10.20140612-0ubuntu1) utopic; urgency=low
>  
>    [ Ubuntu daily release ]
> 
> === modified file 'debian/control'
> --- debian/control	2014-05-29 09:28:16 +0000
> +++ debian/control	2014-06-24 16:02:38 +0000
> @@ -6,7 +6,6 @@
>  Build-Depends: cmake,
>                 curl,
>                 libdbus-cpp-dev (>= 3.0.0),
> -               dbus-test-runner,
>                 debhelper (>= 9),
>                 doxygen,
>                 geoclue-ubuntu-geoip,
> @@ -15,9 +14,13 @@
>                 libboost-program-options-dev,
>                 libboost-system-dev,
>                 libdbus-1-dev,
> +               libdbus-cpp-dev,
>                 libgoogle-glog-dev,
>                 libgtest-dev,
>                 libiw-dev,
> +               libjsoncpp-dev,
> +               libnet-cpp-dev,
> +               libprocess-cpp-dev,
>                 libubuntu-platform-hardware-api-headers,
>                 libubuntu-platform-hardware-api-dev,
>                 libproperties-cpp-dev,
> @@ -28,7 +31,7 @@
>  Vcs-Bzr: https://code.launchpad.net/~phablet-team/location-service/trunk
>  Vcs-Browser: http://bazaar.launchpad.net/~phablet-team/location-service/trunk/files
>  
> -Package: libubuntu-location-service0
> +Package: libubuntu-location-service1
>  Section: libs
>  Architecture: any
>  Multi-Arch: same
> @@ -45,7 +48,7 @@
>  Architecture: any
>  Multi-Arch: foreign
>  Recommends: ubuntu-location-service-doc,
> -Depends: libubuntu-location-service0 (= ${binary:Version}),
> +Depends: libubuntu-location-service1 (= ${binary:Version}),
>           ${misc:Depends},
>  Suggests: ubuntu-location-service-doc,
>  Description: location service aggregating position/velocity/heading
> @@ -54,9 +57,30 @@
>   Contains header files required to develop clients talking to the ubuntu
>   location service.
>  
> +Package: libubuntu-location-service-dbg
> +Section: debug
> +Architecture: any
> +Multi-Arch: foreign
> +Depends: libubuntu-location-service1 (= ${binary:Version}),
> +         ${misc:Depends},
> +Description: location service aggregating position/velocity/heading
> + updates and exporting them over dbus.
> + .
> + Contains debug symbols.
> +
> +Package: ubuntu-location-service-tests
> +Architecture: any
> +Depends: ${misc:Depends},
> +         ${shlibs:Depends},
> +Description: location service aggregating position/velocity/heading
> + updates and exporting them over dbus.
> + .
> + Contains all test executables
> +
>  Package: ubuntu-location-service-bin
>  Architecture: any
> -Depends: ${misc:Depends},
> +Depends: libubuntu-location-service1 (= ${binary:Version}),
> +         ${misc:Depends},
>           ${shlibs:Depends},
>  Breaks: ubuntu-location-service-examples (<< 0.0.2),
>  Replaces: ubuntu-location-service-examples (<< 0.0.2),
> @@ -68,7 +92,8 @@
>  Package: ubuntu-location-service-examples
>  Architecture: any
>  Multi-Arch: same
> -Depends: ${misc:Depends},
> +Depends: libubuntu-location-service1 (= ${binary:Version}),
> +         ${misc:Depends},
>           ${shlibs:Depends},
>           ubuntu-location-service-doc,
>  Description: location service aggregating position/velocity/heading
> 
> === modified file 'debian/copyright'
> --- debian/copyright	2013-06-05 16:59:55 +0000
> +++ debian/copyright	2014-06-24 16:02:38 +0000
> @@ -19,6 +19,24 @@
>   License version 2 can be found in the file
>   `/usr/share/common-licenses/GPL-2'.
>  
> +Files: tests/mongoose.*
> +Copyright: 2004-2013 Sergey Lyubka <valenok at gmail.com>
> +Copyright: 2013-2014 Cesanta Software Limited
> +License: GPL-2+
> + This program is free software; you can redistribute it
> + and/or modify it under the terms of the GNU General
> + Public License as published by the Free Software Foundation;
> + either version 2, or (at your option) any later version.
> + .
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + GNU General Public License for more details.
> + .
> + On Debian systems, the full text of the GNU General Public
> + License version 2 can be found in the file
> + `/usr/share/common-licenses/GPL-2'.
> +
>  Files: *
>  Copyright: 2013 Canonical Ltd.
>  License: LGPL-3
> 
> === modified file 'debian/libubuntu-location-service-dev.install'
> --- debian/libubuntu-location-service-dev.install	2013-06-13 13:57:38 +0000
> +++ debian/libubuntu-location-service-dev.install	2014-06-24 16:02:38 +0000
> @@ -1,3 +1,5 @@
> -usr/include/ubuntu-location-service-0
> +usr/include/ubuntu-location-service-1
>  usr/lib/*/libubuntu-location-service.so
> -usr/lib/pkgconfig/ubuntu-location-service.pc
> +usr/lib/*/libubuntu-location-service-connectivity.so
> +usr/lib/*/pkgconfig/ubuntu-location-service.pc
> +usr/lib/*/pkgconfig/ubuntu-location-service-connectivity.pc
> 
> === renamed file 'debian/libubuntu-location-service0.install' => 'debian/libubuntu-location-service1.install'
> --- debian/libubuntu-location-service0.install	2013-06-13 13:57:38 +0000
> +++ debian/libubuntu-location-service1.install	2014-06-24 16:02:38 +0000
> @@ -1,1 +1,2 @@
>  usr/lib/*/libubuntu-location-service.so.*
> +usr/lib/*/libubuntu-location-service-connectivity.so.*
> 
> === modified file 'debian/rules'
> --- debian/rules	2014-05-05 09:14:35 +0000
> +++ debian/rules	2014-06-24 16:02:38 +0000
> @@ -19,5 +19,8 @@
>  override_dh_install:
>  	dh_install -Xubuntu-location-service.1 --fail-missing
>  
> +override_dh_strip:
> +	dh_strip --dbg-package=libubuntu-location-service-dbg
> +
>  override_dh_auto_configure:
>  	dh_auto_configure -- -DCMAKE_INSTALL_LIBEXECDIR=/usr/lib/$(DEB_HOST_MULTIARCH)/ubuntu-location-service
> 
> === modified file 'debian/ubuntu-location-service-bin.install'
> --- debian/ubuntu-location-service-bin.install	2013-10-08 14:48:43 +0000
> +++ debian/ubuntu-location-service-bin.install	2014-06-24 16:02:38 +0000
> @@ -1,4 +1,4 @@
>  etc/dbus-1/system.d/
>  etc/init/*
>  usr/bin/ubuntu-location-serviced
> -
> +usr/bin/ubuntu-location-serviced-cli
> 
> === modified file 'debian/ubuntu-location-service-examples.install'
> --- debian/ubuntu-location-service-examples.install	2013-10-14 06:11:15 +0000
> +++ debian/ubuntu-location-service-examples.install	2014-06-24 16:02:38 +0000
> @@ -1,2 +1,3 @@
>  usr/lib/*/ubuntu-location-service/examples/client
>  usr/lib/*/ubuntu-location-service/examples/service
> +usr/share/ubuntu-location-service
> 
> === added file 'debian/ubuntu-location-service-tests.install'
> --- debian/ubuntu-location-service-tests.install	1970-01-01 00:00:00 +0000
> +++ debian/ubuntu-location-service-tests.install	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,1 @@
> +usr/bin/uls-tests/*
> 
> === modified file 'doc/Doxyfile.in'
> --- doc/Doxyfile.in	2014-02-09 18:52:25 +0000
> +++ doc/Doxyfile.in	2014-06-24 16:02:38 +0000
> @@ -32,13 +32,13 @@
>  # This could be handy for archiving the generated documentation or
>  # if some version control system is used.
>  
> -PROJECT_NUMBER         = @UBUNTU_LOCATION_SERVICE_VERSION_MAJOR at .@UBUNTU_LOCATION_SERVICE_VERSION_MINOR at .@UBUNTU_LOCATION_SERVICE_VERSION_PATCH@
> +PROJECT_NUMBER         = @LOCATION_SERVICE_VERSION_MAJOR at .@LOCATION_SERVICE_VERSION_MINOR at .@LOCATION_SERVICE_VERSION_PATCH@
>  
>  # Using the PROJECT_BRIEF tag one can provide an optional one line description
>  # for a project that appears at the top of each page and should give viewer
>  # a quick idea about the purpose of the project. Keep the description short.
>  
> -PROJECT_BRIEF          =
> +PROJECT_BRIEF          = "An aggregating location service providing positioning and geocoding capabilities to applications."
>  
>  # With the PROJECT_LOGO tag one can specify an logo or icon that is
>  # included in the documentation. The maximum height of the logo should not
> @@ -266,7 +266,7 @@
>  # func(std::string) {}). This also makes the inheritance and collaboration
>  # diagrams that involve STL classes more complete and accurate.
>  
> -BUILTIN_STL_SUPPORT    = NO
> +BUILTIN_STL_SUPPORT    = YES
>  
>  # If you use Microsoft's C++/CLI language, you should set this option to YES to
>  # enable parsing support.
> @@ -365,7 +365,7 @@
>  # Private class members and static file members will be hidden unless
>  # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
>  
> -EXTRACT_ALL            = NO
> +EXTRACT_ALL            = YES
>  
>  # If the EXTRACT_PRIVATE tag is set to YES all private members of a class
>  # will be included in the documentation.
> @@ -380,7 +380,7 @@
>  # If the EXTRACT_STATIC tag is set to YES all static members of a file
>  # will be included in the documentation.
>  
> -EXTRACT_STATIC         = NO
> +EXTRACT_STATIC         = YES
>  
>  # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
>  # defined locally in source files will be included in the documentation.
> @@ -423,7 +423,7 @@
>  # If set to NO (the default) these declarations will be included in the
>  # documentation.
>  
> -HIDE_FRIEND_COMPOUNDS  = NO
> +HIDE_FRIEND_COMPOUNDS  = YES
>  
>  # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
>  # documentation blocks found inside the body of a function.
> @@ -668,7 +668,7 @@
>  # directories like "/usr/src/myproject". Separate the files or directories
>  # with spaces.
>  
> -INPUT                  = @CMAKE_CURRENT_SOURCE_DIR@/../include
> +INPUT                  = @CMAKE_CURRENT_SOURCE_DIR@ @CMAKE_CURRENT_SOURCE_DIR@/../include
>  
>  # This tag can be used to specify the character encoding of the source files
>  # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
> @@ -728,7 +728,7 @@
>  # directories that contain example code fragments that are included (see
>  # the \include command).
>  
> -EXAMPLE_PATH           = @CMAKE_CURRENT_SOURCE_DIR@/../examples
> +EXAMPLE_PATH           = @CMAKE_CURRENT_SOURCE_DIR@/../tests
>  
>  # If the value of the EXAMPLE_PATH tag contains directories, you can use the
>  # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
> @@ -791,7 +791,7 @@
>  # This can be useful if you have a project on for instance GitHub and want reuse
>  # the introduction page also for the doxygen output.
>  
> -USE_MDFILE_AS_MAINPAGE =
> +USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/README.md
>  
>  #---------------------------------------------------------------------------
>  # configuration options related to source browsing
> @@ -807,7 +807,7 @@
>  # Setting the INLINE_SOURCES tag to YES will include the body
>  # of functions and classes directly in the documentation.
>  
> -INLINE_SOURCES         = YES
> +INLINE_SOURCES         = NO
>  
>  # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
>  # doxygen to hide any special comment blocks from generated source code
> @@ -929,7 +929,7 @@
>  # robust against future updates. Doxygen will copy the style sheet file to
>  # the output directory.
>  
> -HTML_EXTRA_STYLESHEET  =
> +HTML_EXTRA_STYLESHEET  = @CMAKE_CURRENT_SOURCE_DIR@/extra.css
>  
>  # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
>  # other source files which should be copied to the HTML output directory. Note
> @@ -975,7 +975,7 @@
>  # documentation will contain sections that can be hidden and shown after the
>  # page has loaded.
>  
> -HTML_DYNAMIC_SECTIONS  = NO
> +HTML_DYNAMIC_SECTIONS  = YES
>  
>  # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
>  # entries shown in the various tree structured indices initially; the user
> @@ -1145,7 +1145,7 @@
>  # navigation tree you can set this option to NO if you already set
>  # GENERATE_TREEVIEW to YES.
>  
> -DISABLE_INDEX          = NO
> +DISABLE_INDEX          = YES
>  
>  # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
>  # structure should be generated to display hierarchical information.
> @@ -1157,7 +1157,7 @@
>  # Since the tree basically has the same information as the tab index you
>  # could consider to set DISABLE_INDEX to NO when enabling this option.
>  
> -GENERATE_TREEVIEW      = NO
> +GENERATE_TREEVIEW      = YES
>  
>  # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
>  # (range [0,1..20]) that doxygen will group on one line in the generated HTML
> @@ -1234,7 +1234,7 @@
>  # typically be disabled. For large projects the javascript based search engine
>  # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
>  
> -SEARCHENGINE           = NO 
> +SEARCHENGINE           = NO
>  
>  # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
>  # implemented using a web server instead of a web client using Javascript.
> @@ -1293,7 +1293,7 @@
>  # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
>  # generate Latex output.
>  
> -GENERATE_LATEX         = NO
> +GENERATE_LATEX         = YES
>  
>  # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
>  # If a relative path is entered the value of OUTPUT_DIRECTORY will be
> @@ -1319,7 +1319,7 @@
>  # LaTeX documents. This may be useful for small projects and may help to
>  # save some trees in general.
>  
> -COMPACT_LATEX          = NO
> +COMPACT_LATEX          = YES 
>  
>  # The PAPER_TYPE tag can be used to set the paper type that is used
>  # by the printer. Possible values are: a4, letter, legal and
> @@ -1377,7 +1377,7 @@
>  # Note that which sources are shown also depends on other settings
>  # such as SOURCE_BROWSER.
>  
> -LATEX_SOURCE_CODE      = NO
> +LATEX_SOURCE_CODE      = NO 
>  
>  # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
>  # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
> @@ -1434,7 +1434,7 @@
>  # If the GENERATE_MAN tag is set to YES (the default) Doxygen will
>  # generate man pages
>  
> -GENERATE_MAN           = NO
> +GENERATE_MAN           = YES
>  
>  # The MAN_OUTPUT tag is used to specify where the man pages will be put.
>  # If a relative path is entered the value of OUTPUT_DIRECTORY will be
> 
> === modified file 'examples/CMakeLists.txt'
> --- examples/CMakeLists.txt	2013-05-28 14:20:45 +0000
> +++ examples/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -1,7 +1,5 @@
>  add_subdirectory(service)
>  
> -
> -
> -
> -
> -
> +install(
> +  DIRECTORY standalone
> +  DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}/examples)
> \ No newline at end of file
> 
> === modified file 'examples/service/CMakeLists.txt'
> --- examples/service/CMakeLists.txt	2014-01-31 11:08:33 +0000
> +++ examples/service/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -1,13 +1,8 @@
> -find_package(PkgConfig)
> -find_package(Boost COMPONENTS system)
> -find_package(Threads)
> -
> -pkg_check_modules(DBUS dbus-1)
> -pkg_check_modules(DBUS_CPP dbus-cpp)
> +message(STATUS ${Boost_LIBRARIES})
>  include_directories(
>      ${Boost_INCLUDE_DIRS}
>      ${DBUS_INCLUDE_DIRS}
> -    ${DBUS_CPP_INCLUDE_DIRS}/dbus
> +    ${DBUS_CPP_INCLUDE_DIRS}
>  
>  )
>  
> 
> === modified file 'examples/service/client.cpp'
> --- examples/service/client.cpp	2014-01-31 11:08:33 +0000
> +++ examples/service/client.cpp	2014-06-24 16:02:38 +0000
> @@ -17,7 +17,7 @@
>   */
>  #include "program_options.h"
>  
> -#include "com/ubuntu/location/service/stub.h"
> +#include <com/ubuntu/location/service/stub.h>
>  
>  #include <core/dbus/resolver.h>
>  #include <core/dbus/asio/executor.h>
> @@ -26,6 +26,7 @@
>  
>  namespace cul = com::ubuntu::location;
>  namespace culs = com::ubuntu::location::service;
> +namespace culss = com::ubuntu::location::service::session;
>  namespace dbus = core::dbus;
>  
>  int main(int argc, char** argv)
> @@ -53,34 +54,34 @@
>          {"system", dbus::WellKnownBus::system},
>      };
>  
> -    core::dbus::Bus::Ptr bus
> +    dbus::Bus::Ptr bus
>      {
> -        new core::dbus::Bus{lut.at(options.value_for_key<std::string>("bus"))}
> +        new dbus::Bus{lut.at(options.value_for_key<std::string>("bus"))}
>      };
> -    bus->install_executor(core::dbus::asio::make_executor(bus));
> +    bus->install_executor(dbus::asio::make_executor(bus));
>      std::thread t{[bus](){bus->run();}};
>      
>      auto location_service = 
> -            core::dbus::resolve_service_on_bus<culs::Interface, culs::Stub>(bus);
> -        
> -    auto s1 = location_service->create_session_for_criteria(com::ubuntu::location::Criteria{});
> -        
> -    s1->install_position_updates_handler(
> -        [&](const com::ubuntu::location::Update<com::ubuntu::location::Position>& new_position) {
> +            dbus::resolve_service_on_bus<culs::Interface, culs::Stub>(bus);
> +        
> +    auto s1 = location_service->create_session_for_criteria(cul::Criteria{});
> +        
> +    s1->updates().position.changed().connect(
> +        [&](const cul::Update<cul::Position>& new_position) {

Do we need to use & to camputer anythig in here?

>              std::cout << "On position updated: " << new_position << std::endl;
>          });
> -    s1->install_velocity_updates_handler(
> -        [&](const com::ubuntu::location::Update<com::ubuntu::location::Velocity>& new_velocity) {
> +    s1->updates().velocity.changed().connect(
> +        [&](const cul::Update<cul::Velocity>& new_velocity) {
>              std::cout << "On velocity_changed " << new_velocity << std::endl;
>          });
> -    s1->install_heading_updates_handler(
> -        [&](const com::ubuntu::location::Update<com::ubuntu::location::Heading>& new_heading) {
> +    s1->updates().heading.changed().connect(
> +        [&](const cul::Update<cul::Heading>& new_heading) {
>              std::cout << "On heading changed: " << new_heading << std::endl;
>          });
>          
> -    s1->start_position_updates();
> -    s1->start_velocity_updates();
> -    s1->start_heading_updates();
> +    s1->updates().position_status = culss::Interface::Updates::Status::enabled;
> +    s1->updates().heading_status = culss::Interface::Updates::Status::enabled;
> +    s1->updates().velocity_status = culss::Interface::Updates::Status::enabled;
>          
>      if (t.joinable())
>          t.join();
> 
> === modified file 'examples/service/service.cpp'
> --- examples/service/service.cpp	2014-01-31 11:08:33 +0000
> +++ examples/service/service.cpp	2014-06-24 16:02:38 +0000
> @@ -17,10 +17,10 @@
>   */
>  #include "program_options.h"
>  
> -#include "com/ubuntu/location/provider_factory.h"
> +#include <com/ubuntu/location/provider_factory.h>
>  
> -#include "com/ubuntu/location/service/default_configuration.h"
> -#include "com/ubuntu/location/service/implementation.h"
> +#include <com/ubuntu/location/service/default_configuration.h>
> +#include <com/ubuntu/location/service/implementation.h>
>  
>  #include <core/dbus/announcer.h>
>  #include <core/dbus/asio/executor.h>
> @@ -31,6 +31,33 @@
>  namespace culs = com::ubuntu::location::service;
>  namespace dbus = core::dbus;
>  
> +namespace
> +{
> +struct NullReporter : public culs::Harvester::Reporter
> +{
> +    NullReporter() = default;
> +
> +    /** @brief Tell the reporter that it should start operating. */
> +    void start() override
> +    {
> +    }
> +
> +    /** @brief Tell the reporter to shut down its operation. */
> +    void stop()
> +    {
> +    }
> +
> +    /**
> +     * @brief Triggers the reporter to send off the information.
> +     */
> +    void report(const cul::Update<cul::Position>&,
> +                const std::vector<cul::connectivity::WirelessNetwork::Ptr>&,
> +                const std::vector<cul::connectivity::RadioCell::Ptr>&)
> +    {
> +    }
> +};
> +}
> +
>  int main(int argc, char** argv)
>  {
>      cul::ProgramOptions options;
> @@ -119,30 +146,43 @@
>          {"system", dbus::WellKnownBus::system},
>      };
>  
> -    dbus::Bus::Ptr bus
> +    dbus::Bus::Ptr incoming
>      {
>          new dbus::Bus{lut.at(options.value_for_key<std::string>("bus"))}
>      };
> +    incoming->install_executor(dbus::asio::make_executor(incoming));
>  
> -    bus->install_executor(dbus::asio::make_executor(bus));
> +    dbus::Bus::Ptr outgoing
> +    {
> +        new dbus::Bus{lut.at(options.value_for_key<std::string>("bus"))}
> +    };
> +    outgoing->install_executor(dbus::asio::make_executor(outgoing));
>  
>      culs::DefaultConfiguration config;
> -    
> -    auto location_service =
> -            dbus::announce_service_on_bus<
> -                culs::Interface, 
> -                culs::Implementation
> -            >(
> -                bus,
> -                config.the_engine(
> -                    instantiated_providers,
> -                    config.the_provider_selection_policy()),
> -                config.the_permission_manager());
> -    
> -    std::thread t{[bus](){bus->run();}};
> -    
> -    if (t.joinable())
> -        t.join();
> +
> +    culs::Implementation::Configuration configuration
> +    {
> +        incoming,
> +        outgoing,
> +        config.the_engine(instantiated_providers, config.the_provider_selection_policy()),
> +        config.the_permission_manager(),
> +        culs::Harvester::Configuration
> +        {
> +            cul::connectivity::platform_default_manager(),
> +            std::make_shared<NullReporter>()
> +        }
> +    };
> +
> +    auto location_service = std::make_shared<culs::Implementation>(configuration);
> +    
> +    std::thread t1{[incoming](){incoming->run();}};
> +    std::thread t2{[outgoing](){outgoing->run();}};
> +    
> +    if (t1.joinable())
> +        t1.join();
> +
> +    if (t2.joinable())
> +        t2.join();
>  
>      return EXIT_SUCCESS;
>  }
> 
> === added directory 'examples/standalone'
> === added directory 'examples/standalone/connectivity'
> === added file 'examples/standalone/connectivity/CMakeLists.txt'
> --- examples/standalone/connectivity/CMakeLists.txt	1970-01-01 00:00:00 +0000
> +++ examples/standalone/connectivity/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,41 @@
> +cmake_minimum_required(VERSION 2.8)
> +
> +project(connectivity)
> +
> +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
> +
> +find_package(PkgConfig)
> +find_package(Threads)
> +
> +pkg_check_modules(
> +  DBUS_CPP 
> +  dbus-cpp REQUIRED)
> +
> +pkg_check_modules(
> +  PROCESS_CPP 
> +  process-cpp REQUIRED)
> +
> +pkg_check_modules(
> +  LOCATION_CONNECTIVITY 
> +  ubuntu-location-service-connectivity REQUIRED)
> +
> +include_directories(
> +  ${DBUS_CPP_INCLUDE_DIRS}
> +  ${PROCESS_CPP_INCLUDE_DIRS}
> +  ${LOCATION_CONNECTIVITY_INCLUDE_DIRS})
> +
> +add_executable(
> +  connectivity
> +
> +  connectivity.cpp)
> +
> +target_link_libraries(
> +  connectivity
> +
> +  ${CMAKE_THREAD_LIBS_INIT}
> +
> +  ${DBUS_CPP_LDFLAGS}
> +  ${PROCESS_CPP_LDFLAGS}
> +  ${LOCATION_CONNECTIVITY_LDFLAGS})
> +
> +
> 
> === added file 'examples/standalone/connectivity/connectivity.cpp'
> --- examples/standalone/connectivity/connectivity.cpp	1970-01-01 00:00:00 +0000
> +++ examples/standalone/connectivity/connectivity.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,201 @@
> +#include <com/ubuntu/location/connectivity/manager.h>
> +
> +#include <core/posix/signal.h>
> +
> +#include <cstdlib>
> +
> +#include <thread>
> +
> +namespace location = com::ubuntu::location;
> +
> +namespace
> +{
> +// Just convenience to safe some typing.
> +typedef std::vector<location::connectivity::RadioCell> RadioCells;
> +typedef std::vector<location::connectivity::WirelessNetwork::Ptr> WirelessNetworks;
> +}
> +
> +// This example illustrates the usage of the location-service-specific connectivity API.
> +// The setup for obtaining measurements of wifis and radio cells is as follows:
> +//
> +//   (1.) Obtain an instance of location::connectivity::Manager.
> +//   (2.) Connect to the changed signals of the wifi and cell properties and react according to your component's requirements.
> +//   (3.) Bootstrap your own setup by explicitly getting all visible wifis and connected cells.
> +int main(int argc, char** argv)
> +{
> +    // We catch sig-term to exit cleanly.
> +    auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term});
> +    trap->signal_raised().connect([trap](core::posix::Signal)
> +                                  {
> +                                      trap->stop();
> +                                  });
> +
> +    // Trying to acquire a default implementation.
> +    auto cm = location::connectivity::platform_default_manager();
> +
> +    if (not cm)
> +    {
> +        std::cerr << "Could not get hold of a connectivity::Manager implementation, aborting..." << std::endl;
> +        std::exit(1);
> +    }
> +
> +    // Subscribe to wifi added/removed signals.
> +    cm->wireless_network_added().connect([](const location::connectivity::WirelessNetwork::Ptr& wifi)
> +    {
> +        std::cout << "Visible wireless network was added: " << *wifi << std::endl;
> +
> +        // We don't want to keep the object alive
> +        std::weak_ptr<location::connectivity::WirelessNetwork> wp
> +        {
> +            wifi
> +        };
> +
> +
> +
> +        // Subscribe to signal strength and last_seen updates. Please note that this is not considering
> +        // the case of subscribing to already known wifis. We leave this up
> +        // to consumers of the api.
> +        wifi->last_seen().changed().connect([wp](const std::chrono::system_clock::time_point& tp)
> +        {
> +            auto sp = wp.lock();
> +            if (sp)
> +                std::cout << "Signal strength changed for wifi " << sp->ssid().get() << ": " << tp.time_since_epoch().count() << std::endl;
> +        });
> +
> +        wifi->signal_strength().changed().connect([wp](const location::connectivity::WirelessNetwork::SignalStrength& s)
> +        {
> +            auto sp = wp.lock();
> +            if (sp)
> +                std::cout << "Signal strength changed for wifi " << sp->ssid().get() << ": " << s << std::endl;
> +        });
> +    });
> +
> +    cm->wireless_network_removed().connect([](const location::connectivity::WirelessNetwork::Ptr& wifi)
> +    {
> +        std::cout << "Visible wireless network was removed: " << wifi->ssid().get() << std::endl;
> +    });
> +
> +    // Iterate over all radio cells that the device is connected with.
> +    cm->enumerate_connected_radio_cells([](const location::connectivity::RadioCell::Ptr& cell)
> +    {
> +        std::cout << *cell << std::endl;
> +
> +        std::weak_ptr<location::connectivity::RadioCell> wp{cell};
> +
> +        // Subscribe to changes on the cell
> +        cell->changed().connect([wp]()
> +        {
> +            auto sp = wp.lock();
> +
> +            if (sp)
> +                std::cout << "Something changed on a radio cell: " << *sp << std::endl;
> +        });
> +    });
> +
> +    cm->connected_cell_added().connect([](const location::connectivity::RadioCell::Ptr& cell)
> +    {
> +        std::cout << *cell << std::endl;
> +
> +        // Subscribe to changes on the cell
> +        cell->changed().connect([]()
> +        {
> +            std::cout << "Something changed on a radio cell." << std::endl;
> +        });
> +    });
> +
> +    cm->connected_cell_removed().connect([](const location::connectivity::RadioCell::Ptr& cell)
> +    {
> +        std::cout << *cell << std::endl;
> +    });
> +
> +    // Iterate over all networks that are visible right now.
> +    cm->enumerate_visible_wireless_networks([](const location::connectivity::WirelessNetwork::Ptr& wifi)
> +    {
> +        std::cout << *wifi << std::endl;
> +
> +        // We don't want to keep the object alive
> +        std::weak_ptr<location::connectivity::WirelessNetwork> wp
> +        {
> +            wifi
> +        };
> +
> +        // Subscribe to last-seen updates.
> +        wifi->last_seen().changed().connect([wp](const std::chrono::system_clock::time_point& tp)
> +        {
> +            auto sp = wp.lock();
> +            if (sp)
> +                std::cout << "Last seen changed for wifi " << *sp << std::endl;
> +        });
> +
> +        // Subscribe to signal strength updates. Please note that this is not considering
> +        // the case of subscribing to already known wifis. We leave this up
> +        // to consumers of the api.
> +        wifi->signal_strength().changed().connect([wp](const location::connectivity::WirelessNetwork::SignalStrength& s)
> +        {
> +            auto sp = wp.lock();
> +            if (sp)
> +                std::cout << "Signal strength changed for wifi: " << *sp << std::endl;
> +        });
> +    });
> +    
> +    // Subscribe to end-of-scan signals
> +    cm->wireless_network_scan_finished().connect([]()
> +    {
> +        std::cout << "A wireless network scan finished." << std::endl;
> +    });
> +
> +    // Request a scan for wireless networks.
> +    try
> +    {
> +        cm->request_scan_for_wireless_networks();
> +    } catch(const std::runtime_error& e)
> +    {
> +        std::cerr << e.what() << std::endl;
> +    }
> +
> +    bool cancelled = false;
> +
> +    std::thread t1
> +    {
> +        [cm, &cancelled]()
> +        {
> +            while (not cancelled)
> +            {
> +                cm->enumerate_visible_wireless_networks([](const location::connectivity::WirelessNetwork::Ptr&)
> +                {
> +                    // We do nothing with the actual values and just keep the thread running
> +                    // to put some load on the infrastructure.
> +                });
> +            }
> +        }
> +    };
> +
> +    std::thread t2
> +    {
> +        [cm, &cancelled]()
> +        {
> +            while (not cancelled)
> +            {
> +                cm->enumerate_connected_radio_cells([](const location::connectivity::RadioCell::Ptr&)
> +                {
> +                    // We do nothing with the actual values and just keep the thread running
> +                    // to put some load on the infrastructure.
> +                });
> +            }
> +        }
> +    };
> +
> +    trap->run();
> +
> +    cancelled = true;
> +
> +    if (t1.joinable())
> +        t1.join();
> +
> +    if (t2.joinable())
> +        t2.join();
> +
> +    return 0;
> +}    
> +
> +
> 
> === modified file 'include/CMakeLists.txt'
> --- include/CMakeLists.txt	2013-05-28 14:20:45 +0000
> +++ include/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -1,4 +1,4 @@
>  install(
> -	DIRECTORY location_service/com
> -	DESTINATION include/ubuntu-location-service-${UBUNTU_LOCATION_SERVICE_VERSION_MAJOR}
> -)
> \ No newline at end of file
> +    DIRECTORY location_service/com
> +    DESTINATION include/ubuntu-location-service-${UBUNTU_LOCATION_SERVICE_VERSION_MAJOR}
> +)
> 
> === removed file 'include/location_service/com/ubuntu/location/channel.h'
> --- include/location_service/com/ubuntu/location/channel.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/channel.h	1970-01-01 00:00:00 +0000
> @@ -1,41 +0,0 @@
> -/*
> - * Copyright © 2012-2013 Canonical Ltd.
> - *
> - * This program is free software: you can redistribute it and/or modify it
> - * under the terms of the GNU Lesser General Public License version 3,
> - * as published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public License
> - * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> - *
> - * Authored by: Thomas Voß <thomas.voss at canonical.com>
> - */
> -#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CHANNEL_H_
> -#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CHANNEL_H_
> -
> -#include <boost/signals2.hpp>
> -
> -#include <memory>
> -#include <set>
> -
> -namespace com
> -{
> -namespace ubuntu
> -{
> -namespace location
> -{
> -template<typename T>
> -using Channel = boost::signals2::signal<void(const T&)>;
> -
> -typedef boost::signals2::scoped_connection ScopedChannelConnection;
> -typedef boost::signals2::connection ChannelConnection;
> -}
> -}
> -}
> -
> -#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_CHANNEL_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/clock.h'
> --- include/location_service/com/ubuntu/location/clock.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/clock.h	2014-06-24 16:02:38 +0000
> @@ -26,15 +26,41 @@
>  {
>  namespace location
>  {
> +/**
> + * @brief Defines the timebase of the location service.
> + */
>  struct Clock
>  {
> +    /** @brief The underlying clock we are assuming for all time-stamping purposes. */
> +    typedef std::chrono::high_resolution_clock Type;
> +
> +    /**
> +     * @brief Duration type of the location service clock.
> +     */
>      typedef std::chrono::high_resolution_clock::duration Duration;
> +
> +    /**
> +     * @brief Timestamp type of the location service clock.
> +     */
>      typedef std::chrono::high_resolution_clock::time_point Timestamp;
>  
> +    /**
> +     * @brief Samples a timestamp from the clock.
> +     * @return The current time.
> +     */
>      static inline Timestamp now()
>      {
>          return std::chrono::high_resolution_clock::now();
>      }
> +
> +    /**
> +     * @brief Samples a timestamp from the clock.
> +     * @return The minimum point in time representable by this clock.
> +     */
> +    static inline Timestamp beginning_of_time()
> +    {
> +        return std::chrono::high_resolution_clock::time_point::min();
> +    }
>  };
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/codec.h'
> --- include/location_service/com/ubuntu/location/codec.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/codec.h	2014-06-24 16:02:38 +0000
> @@ -18,16 +18,16 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CODEC_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CODEC_H_
>  
> -#include "com/ubuntu/location/accuracy.h"
> -#include "com/ubuntu/location/criteria.h"
> -#include "com/ubuntu/location/heading.h"
> -#include "com/ubuntu/location/position.h"
> -#include "com/ubuntu/location/update.h"
> -#include "com/ubuntu/location/velocity.h"
> -#include "com/ubuntu/location/units/units.h"
> -#include "com/ubuntu/location/wgs84/altitude.h"
> -#include "com/ubuntu/location/wgs84/latitude.h"
> -#include "com/ubuntu/location/wgs84/longitude.h"
> +#include <com/ubuntu/location/criteria.h>
> +#include <com/ubuntu/location/heading.h>
> +#include <com/ubuntu/location/position.h>
> +#include <com/ubuntu/location/space_vehicle.h>
> +#include <com/ubuntu/location/update.h>
> +#include <com/ubuntu/location/velocity.h>
> +#include <com/ubuntu/location/units/units.h>
> +#include <com/ubuntu/location/wgs84/altitude.h>
> +#include <com/ubuntu/location/wgs84/latitude.h>
> +#include <com/ubuntu/location/wgs84/longitude.h>
>  
>  #include <core/dbus/codec.h>
>  
> @@ -44,6 +44,7 @@
>      {
>          return ArgumentType::floating_point;
>      }
> +
>      constexpr static bool is_basic_type()
>      {
>          return true;
> @@ -62,317 +63,283 @@
>  }
>  
>  template<typename T>
> +struct Codec<com::ubuntu::location::Optional<T>>
> +{
> +    static void encode_argument(Message::Writer& writer, const com::ubuntu::location::Optional<T>& in)
> +    {
> +        bool has_value{in};
> +        Codec<bool>::encode_argument(writer, has_value);
> +        if (has_value)
> +            Codec<typename com::ubuntu::location::Optional<T>::value_type>::encode_argument(writer, *in);
> +    }
> +
> +    static void decode_argument(Message::Reader& reader, com::ubuntu::location::Optional<T>& in)
> +    {
> +        bool has_value{false};
> +        Codec<bool>::decode_argument(reader, has_value);
> +        if (has_value)
> +        {
> +            typename com::ubuntu::location::Optional<T>::value_type value;
> +            Codec<typename com::ubuntu::location::Optional<T>::value_type>::decode_argument(reader, value);
> +            in = value;
> +        } else
> +        {
> +            in.reset();
> +        }
> +    }
> +};
> +
> +template<typename T>
>  struct Codec<com::ubuntu::location::units::Quantity<T>>
>  {
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::units::Quantity<T>& in)
> +    static void encode_argument(Message::Writer& writer, const com::ubuntu::location::units::Quantity<T>& in)
>      {
> -        Codec<typename com::ubuntu::location::units::Quantity<T>::value_type>::encode_argument(out, in.value());
> +        Codec<typename com::ubuntu::location::units::Quantity<T>::value_type>::encode_argument(writer, in.value());
>      }
>  
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::units::Quantity<T>& in)
> +    static void decode_argument(Message::Reader& reader, com::ubuntu::location::units::Quantity<T>& in)
>      {
>          typename com::ubuntu::location::units::Quantity<T>::value_type value;
> -        Codec<typename com::ubuntu::location::units::Quantity<T>::value_type>::decode_argument(out, value);
> +        Codec<typename com::ubuntu::location::units::Quantity<T>::value_type>::decode_argument(reader, value);
>          in = com::ubuntu::location::units::Quantity<T>::from_value(value);
> -    }    
> -};
> -
> -namespace helper
> -{
> -template<typename T, typename U>
> -struct TypeMapper<com::ubuntu::location::wgs84::Coordinate<T,U>>
> -{
> -    constexpr static ArgumentType type_value()
> -    {
> -        return ArgumentType::structure;
> -    }
> -    constexpr static bool is_basic_type()
> -    {
> -        return false;
> -    }
> -    constexpr static bool requires_signature()
> -    {
> -        return true;
> -    }
> -
> -    static std::string signature()
> -    {
> -        static const std::string s =
> -            DBUS_STRUCT_BEGIN_CHAR_AS_STRING +
> -                TypeMapper<com::ubuntu::location::units::Quantity<U>>::signature() +
> -            DBUS_STRUCT_END_CHAR_AS_STRING;
> -        return s;
> -    }
> -};
> -}
> +    }
> +};
>  
>  template<typename T, typename U>
>  struct Codec<com::ubuntu::location::wgs84::Coordinate<T,U>>
>  {
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::wgs84::Coordinate<T, U>& in)
> -    {
> -        Codec<com::ubuntu::location::units::Quantity<U>>::encode_argument(out, in.value);
> -    }
> -
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::wgs84::Coordinate<T, U>& in)
> -    {
> -        Codec<com::ubuntu::location::units::Quantity<U>>::decode_argument(out, in.value);
> -    }    
> -};
> -
> -namespace helper
> -{
> -template<>
> -struct TypeMapper<com::ubuntu::location::Position>
> -{
> -    constexpr static ArgumentType type_value()
> -    {
> -        return ArgumentType::structure;
> -    }
> -    constexpr static bool is_basic_type()
> -    {
> -        return false;
> -    }
> -    constexpr static bool requires_signature()
> -    {
> -        return true;
> -    }
> -
> -    static std::string signature()
> -    {
> -        static const std::string s =
> -                TypeMapper<uint64_t>::signature() + 
> -                TypeMapper<com::ubuntu::location::wgs84::Latitude>::signature() +
> -                TypeMapper<com::ubuntu::location::wgs84::Longitude>::signature() +
> -                TypeMapper<com::ubuntu::location::wgs84::Altitude>::signature();
> -        return s;
> -    }
> -};
> -}
> +    static void encode_argument(Message::Writer& writer, const com::ubuntu::location::wgs84::Coordinate<T, U>& in)
> +    {
> +        Codec<com::ubuntu::location::units::Quantity<U>>::encode_argument(writer, in.value);
> +    }
> +
> +    static void decode_argument(Message::Reader& reader, com::ubuntu::location::wgs84::Coordinate<T, U>& in)
> +    {
> +        Codec<com::ubuntu::location::units::Quantity<U>>::decode_argument(reader, in.value);
> +    }
> +};
>  
>  template<>
>  struct Codec<com::ubuntu::location::Position>
>  {
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::Position& in)
> -    {
> -        Codec<uint64_t>::encode_argument(out, in.flags().to_ulong());
> -        if (in.has_latitude())
> -            Codec<com::ubuntu::location::wgs84::Latitude>::encode_argument(out, in.latitude());
> -        if (in.has_longitude())
> -            Codec<com::ubuntu::location::wgs84::Longitude>::encode_argument(out, in.longitude());
> -        if (in.has_altitude())
> -            Codec<com::ubuntu::location::wgs84::Altitude>::encode_argument(out, in.altitude());
> -    }
> -
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::Position& in)
> -    {
> -        com::ubuntu::location::wgs84::Latitude lat;
> -        com::ubuntu::location::wgs84::Longitude lon;
> -        com::ubuntu::location::wgs84::Altitude alt;
> -        uint64_t flags_on_wire;
> -        Codec<uint64_t>::decode_argument(out, flags_on_wire);
> -
> -        com::ubuntu::location::Position::Flags flags{flags_on_wire};
> -        if (flags.test(com::ubuntu::location::Position::latitude_flag))
> -        {
> -            Codec<com::ubuntu::location::wgs84::Latitude>::decode_argument(out, lat);
> -            in.latitude(lat);
> -        }
> -        if (flags.test(com::ubuntu::location::Position::latitude_flag))
> -        {
> -            Codec<com::ubuntu::location::wgs84::Longitude>::decode_argument(out, lon);
> -            in.longitude(lon);
> -        }
> -        if (flags.test(com::ubuntu::location::Position::altitude_flag))
> -        {       
> -            Codec<com::ubuntu::location::wgs84::Altitude>::decode_argument(out, alt);
> -            in.altitude(alt);
> -        }
> -    }
> -};
> -
> -namespace helper
> -{
> -template<>
> -struct TypeMapper<com::ubuntu::location::Velocity>
> -{
> -    constexpr static ArgumentType type_value()
> -    {
> -        return ArgumentType::structure;
> -    }
> -    constexpr static bool is_basic_type()
> -    {
> -        return false;
> -    }
> -    constexpr static bool requires_signature()
> -    {
> -        return true;
> -    }
> -
> -    static std::string signature()
> -    {
> -        static const std::string s =
> -            DBUS_STRUCT_BEGIN_CHAR_AS_STRING +
> -                TypeMapper<typename com::ubuntu::location::Velocity::Quantity>::signature() +
> -            DBUS_STRUCT_END_CHAR_AS_STRING;
> -        return s;
> -    }
> -};
> -}
> -
> -template<>
> -struct Codec<com::ubuntu::location::Velocity>
> -{
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::Velocity& in)
> -    {
> -        Codec<typename com::ubuntu::location::Velocity::Quantity>::encode_argument(out, in.value);
> -    }
> -
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::Velocity& in)
> -    {
> -        Codec<typename com::ubuntu::location::Velocity::Quantity>::decode_argument(out, in.value);
> -    }
> -};
> -
> -namespace helper
> -{
> -template<>
> -struct TypeMapper<com::ubuntu::location::Heading>
> -{
> -    constexpr static ArgumentType type_value()
> -    {
> -        return ArgumentType::structure;
> -    }
> -    constexpr static bool is_basic_type()
> -    {
> -        return false;
> -    }
> -    constexpr static bool requires_signature()
> -    {
> -        return true;
> -    }
> -
> -    static std::string signature()
> -    {
> -        static const std::string s =
> -            DBUS_STRUCT_BEGIN_CHAR_AS_STRING +
> -                TypeMapper<typename com::ubuntu::location::Heading::Quantity>::signature() +
> -            DBUS_STRUCT_END_CHAR_AS_STRING;
> -        return s;
> -    }
> -};
> -}
> -
> -template<>
> -struct Codec<com::ubuntu::location::Heading>
> -{
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::Heading& in)
> -    {
> -        Codec<typename com::ubuntu::location::Heading::Quantity>::encode_argument(out, in.value);
> -    }
> -
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::Heading& in)
> -    {
> -        Codec<typename com::ubuntu::location::Heading::Quantity>::decode_argument(out, in.value);
> -    }
> -};
> -
> -namespace helper
> -{
> -template<typename T>
> -struct TypeMapper<com::ubuntu::location::Accuracy<T>>
> -{
> -    constexpr static ArgumentType type_value()
> -    {
> -        return ArgumentType::structure;
> -    }
> -    constexpr static bool is_basic_type()
> -    {
> -        return false;
> -    }
> -    constexpr static bool requires_signature()
> -    {
> -        return true;
> -    }
> -
> -    static std::string signature()
> -    {
> -        static const std::string s =
> -            DBUS_STRUCT_BEGIN_CHAR_AS_STRING +
> -            TypeMapper<T>::signature() +
> -            DBUS_STRUCT_END_CHAR_AS_STRING;
> -        return s;
> -    }
> -};
> -}
> -
> -template<typename T>
> -struct Codec<com::ubuntu::location::Accuracy<T>>
> -{
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::Accuracy<T>& in)
> -    {
> -        Codec<T>::encode_argument(out, in.value);
> -    }
> -
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::Accuracy<T>& in)
> -    {
> -        Codec<T>::decode_argument(out, in.value);
> -    }    
> -};
> -
> -namespace helper
> -{
> -template<>
> -struct TypeMapper<com::ubuntu::location::Criteria>
> -{
> -    constexpr static ArgumentType type_value()
> -    {
> -        return ArgumentType::structure;
> -    }
> -    constexpr static bool is_basic_type()
> -    {
> -        return false;
> -    }
> -    constexpr static bool requires_signature()
> -    {
> -        return true;
> -    }
> -
> -    static std::string signature()
> -    {
> -        static const std::string s =
> -            DBUS_STRUCT_BEGIN_CHAR_AS_STRING +
> -                helper::TypeMapper<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Latitude>>::signature() +
> -                helper::TypeMapper<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Longitude>>::signature() +
> -                helper::TypeMapper<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Altitude>>::signature() +
> -                helper::TypeMapper<com::ubuntu::location::Accuracy<com::ubuntu::location::Velocity>>::signature() +
> -                helper::TypeMapper<com::ubuntu::location::Accuracy<com::ubuntu::location::Heading>>::signature() +
> -            DBUS_STRUCT_END_CHAR_AS_STRING;
> -        return s;
> -    }
> -};
> -}
> +    typedef com::ubuntu::location::Position::Accuracy::Horizontal HorizontalAccuracy;
> +    typedef com::ubuntu::location::Position::Accuracy::Vertical VerticalAccuracy;
> +
> +    static void encode_argument(Message::Writer& writer, const com::ubuntu::location::Position& in)
> +    {
> +        Codec<com::ubuntu::location::wgs84::Latitude>::encode_argument(writer, in.latitude);
> +        Codec<com::ubuntu::location::wgs84::Longitude>::encode_argument(writer, in.longitude);
> +        Codec<com::ubuntu::location::Optional<com::ubuntu::location::wgs84::Altitude>>::encode_argument(writer, in.altitude);
> +
> +        Codec<com::ubuntu::location::Optional<HorizontalAccuracy>>::encode_argument(writer, in.accuracy.horizontal);
> +        Codec<com::ubuntu::location::Optional<VerticalAccuracy>>::encode_argument(writer, in.accuracy.vertical);
> +    }
> +
> +    static void decode_argument(Message::Reader& reader, com::ubuntu::location::Position& in)
> +    {
> +        Codec<com::ubuntu::location::wgs84::Latitude>::decode_argument(reader, in.latitude);
> +        Codec<com::ubuntu::location::wgs84::Longitude>::decode_argument(reader, in.longitude);
> +        Codec<com::ubuntu::location::Optional<com::ubuntu::location::wgs84::Altitude>>::decode_argument(reader, in.altitude);
> +
> +        Codec<com::ubuntu::location::Optional<HorizontalAccuracy>>::decode_argument(reader, in.accuracy.horizontal);
> +        Codec<com::ubuntu::location::Optional<VerticalAccuracy>>::decode_argument(reader, in.accuracy.vertical);
> +    }
> +};
> +
> +
> +namespace helper
> +{
> +template<>
> +struct TypeMapper<com::ubuntu::location::SpaceVehicle::Key>
> +{
> +    constexpr static ArgumentType type_value()
> +    {
> +        return ArgumentType::structure;
> +    }
> +    constexpr static bool is_basic_type()
> +    {
> +        return false;
> +    }
> +    constexpr static bool requires_signature()
> +    {
> +        return true;
> +    }
> +
> +    static std::string signature()
> +    {
> +        static const std::string s =
> +                helper::TypeMapper<std::uint32_t>::signature() +
> +                helper::TypeMapper<std::uint32_t>::signature();
> +        return s;
> +    }
> +};
> +template<>
> +struct TypeMapper<com::ubuntu::location::SpaceVehicle>
> +{
> +    constexpr static ArgumentType type_value()
> +    {
> +        return ArgumentType::structure;
> +    }
> +    constexpr static bool is_basic_type()
> +    {
> +        return false;
> +    }
> +    constexpr static bool requires_signature()
> +    {
> +        return true;
> +    }
> +
> +    inline static std::string signature()
> +    {
> +        std::string s =
> +            DBUS_STRUCT_BEGIN_CHAR_AS_STRING +
> +                helper::TypeMapper<com::ubuntu::location::SpaceVehicle::Key>::signature() +
> +                helper::TypeMapper<float>::signature() +
> +                helper::TypeMapper<bool>::signature() +
> +                helper::TypeMapper<bool>::signature() +
> +                helper::TypeMapper<bool>::signature() +
> +                helper::TypeMapper<com::ubuntu::location::units::Quantity<com::ubuntu::location::units::PlaneAngle>>::signature() +
> +                helper::TypeMapper<com::ubuntu::location::units::Quantity<com::ubuntu::location::units::PlaneAngle>>::signature() +
> +            DBUS_STRUCT_END_CHAR_AS_STRING;
> +        return s;
> +    }
> +};
> +}
> +
> +template<>
> +struct Codec<com::ubuntu::location::SpaceVehicle::Key>
> +{
> +    static void encode_argument(Message::Writer& writer, const com::ubuntu::location::SpaceVehicle::Key& in)
> +    {
> +        writer.push_uint32(static_cast<std::uint32_t>(in.type));
> +        writer.push_uint32(in.id);
> +    }
> +
> +    static void decode_argument(Message::Reader& reader, com::ubuntu::location::SpaceVehicle::Key& in)
> +    {
> +        in.type = static_cast<com::ubuntu::location::SpaceVehicle::Type>(reader.pop_uint32());
> +        in.id = reader.pop_uint32();
> +    }
> +};
> +
> +template<>
> +struct Codec<com::ubuntu::location::SpaceVehicle>
> +{
> +    inline static void encode_argument(Message::Writer& writer, const com::ubuntu::location::SpaceVehicle& in)
> +    {
> +        auto sub = writer.open_structure();
> +
> +        Codec<com::ubuntu::location::SpaceVehicle::Key>::encode_argument(sub, in.key);
> +        sub.push_floating_point(in.snr);
> +        sub.push_boolean(in.has_almanac_data);
> +        sub.push_boolean(in.has_ephimeris_data);
> +        sub.push_boolean(in.used_in_fix);
> +        Codec<com::ubuntu::location::units::Quantity<com::ubuntu::location::units::PlaneAngle>>::encode_argument(sub, in.azimuth);
> +        Codec<com::ubuntu::location::units::Quantity<com::ubuntu::location::units::PlaneAngle>>::encode_argument(sub, in.elevation);
> +
> +        writer.close_structure(std::move(sub));
> +    }
> +
> +    inline static void decode_argument(Message::Reader& reader, com::ubuntu::location::SpaceVehicle& in)
> +    {
> +        auto sub = reader.pop_structure();
> +
> +        Codec<com::ubuntu::location::SpaceVehicle::Key>::decode_argument(sub, in.key);
> +        in.snr = sub.pop_floating_point();
> +        in.has_almanac_data = sub.pop_boolean();
> +        in.has_ephimeris_data = sub.pop_boolean();
> +        in.used_in_fix = sub.pop_boolean();
> +        Codec<com::ubuntu::location::units::Quantity<com::ubuntu::location::units::PlaneAngle>>::decode_argument(sub, in.azimuth);
> +        Codec<com::ubuntu::location::units::Quantity<com::ubuntu::location::units::PlaneAngle>>::decode_argument(sub, in.elevation);
> +    }
> +};
> +
> +namespace helper
> +{
> +template<>
> +struct TypeMapper<std::map<com::ubuntu::location::SpaceVehicle::Key, com::ubuntu::location::SpaceVehicle>>
> +{
> +    constexpr static ArgumentType type_value()
> +    {
> +        return ArgumentType::array;
> +    }
> +    constexpr static bool is_basic_type()
> +    {
> +        return false;
> +    }
> +    constexpr static bool requires_signature()
> +    {
> +        return true;
> +    }
> +
> +    static std::string signature()
> +    {
> +        static const std::string s = DBUS_TYPE_ARRAY_AS_STRING + TypeMapper<com::ubuntu::location::SpaceVehicle>::signature();
> +        return s;
> +    }
> +};
> +}
> +template<>
> +struct Codec<std::map<com::ubuntu::location::SpaceVehicle::Key, com::ubuntu::location::SpaceVehicle>>
> +{
> +    inline static void encode_argument(Message::Writer& writer, const std::map<com::ubuntu::location::SpaceVehicle::Key, com::ubuntu::location::SpaceVehicle>& arg)
> +    {
> +        types::Signature signature(helper::TypeMapper<com::ubuntu::location::SpaceVehicle>::signature());
> +        auto sub = writer.open_array(signature);
> +
> +        for(const auto& element : arg)
> +        {
> +            Codec<com::ubuntu::location::SpaceVehicle>::encode_argument(sub, element.second);
> +        }
> +
> +        writer.close_array(std::move(sub));
> +    }
> +
> +    inline static void decode_argument(Message::Reader& reader, std::map<com::ubuntu::location::SpaceVehicle::Key, com::ubuntu::location::SpaceVehicle>& out)
> +    {
> +        auto sub = reader.pop_array();
> +        while (sub.type() != ArgumentType::invalid)
> +        {
> +            com::ubuntu::location::SpaceVehicle sv;
> +            Codec<com::ubuntu::location::SpaceVehicle>::decode_argument(sub, sv);
> +            out.insert(std::make_pair(sv.key, sv));
> +        }
> +    }
> +};
>  
>  template<>
>  struct Codec<com::ubuntu::location::Criteria>
>  {
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::Criteria& in)
> -    {
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Latitude>>::encode_argument(out, in.latitude_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Longitude>>::encode_argument(out, in.longitude_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Altitude>>::encode_argument(out, in.altitude_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::Velocity>>::encode_argument(out, in.velocity_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::Heading>>::encode_argument(out, in.heading_accuracy);
> -    }
> -
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::Criteria& in)
> -    {
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Latitude>>::decode_argument(out, in.latitude_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Longitude>>::decode_argument(out, in.longitude_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::wgs84::Altitude>>::decode_argument(out, in.altitude_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::Velocity>>::decode_argument(out, in.velocity_accuracy);
> -        Codec<com::ubuntu::location::Accuracy<com::ubuntu::location::Heading>>::decode_argument(out, in.heading_accuracy);
> -    }    
> +    typedef com::ubuntu::location::units::Quantity<com::ubuntu::location::units::Length> HorizontalAccuracy;
> +    typedef com::ubuntu::location::units::Quantity<com::ubuntu::location::units::Length> VerticalAccuracy;

Although I understand the separation of the accuracy, should we do the math and return it as a single value?? Nevertheless I think we should add a comment and speicify what was used to calculate it, I'm assuming CEP68 was used.

> +    typedef com::ubuntu::location::units::Quantity<com::ubuntu::location::units::Velocity> VelocityAccuracy;
> +    typedef com::ubuntu::location::units::Quantity<com::ubuntu::location::units::PlaneAngle> HeadingAccuracy;
> +
> +    static void encode_argument(Message::Writer& writer, const com::ubuntu::location::Criteria& in)
> +    {
> +        Codec<bool>::encode_argument(writer, in.requires.position);
> +        Codec<bool>::encode_argument(writer, in.requires.altitude);
> +        Codec<bool>::encode_argument(writer, in.requires.heading);
> +        Codec<bool>::encode_argument(writer, in.requires.velocity);
> +
> +        Codec<HorizontalAccuracy>::encode_argument(writer, in.accuracy.horizontal);
> +        Codec<com::ubuntu::location::Optional<VerticalAccuracy>>::encode_argument(writer, in.accuracy.vertical);
> +        Codec<com::ubuntu::location::Optional<VelocityAccuracy>>::encode_argument(writer, in.accuracy.velocity);
> +        Codec<com::ubuntu::location::Optional<HeadingAccuracy>>::encode_argument(writer, in.accuracy.heading);
> +    }
> +
> +    static void decode_argument(Message::Reader& reader, com::ubuntu::location::Criteria& in)
> +    {
> +        Codec<bool>::decode_argument(reader, in.requires.position);
> +        Codec<bool>::decode_argument(reader, in.requires.altitude);
> +        Codec<bool>::decode_argument(reader, in.requires.heading);
> +        Codec<bool>::decode_argument(reader, in.requires.velocity);
> +
> +        Codec<HorizontalAccuracy>::decode_argument(reader, in.accuracy.horizontal);
> +        Codec<com::ubuntu::location::Optional<VerticalAccuracy>>::decode_argument(reader, in.accuracy.vertical);
> +        Codec<com::ubuntu::location::Optional<VelocityAccuracy>>::decode_argument(reader, in.accuracy.velocity);
> +        Codec<com::ubuntu::location::Optional<HeadingAccuracy>>::decode_argument(reader, in.accuracy.heading);
> +    }
>  };
>  namespace helper
>  {
> @@ -405,18 +372,16 @@
>  template<typename T>
>  struct Codec<com::ubuntu::location::Update<T>>
>  {
> -    static void encode_argument(core::dbus::Message::Writer& out, const com::ubuntu::location::Update<T>& in)
> +    static void encode_argument(Message::Writer& writer, const com::ubuntu::location::Update<T>& in)
>      {
> -        Codec<T>::encode_argument(out, in.value);
> -        Codec<int64_t>::encode_argument(out, in.when.time_since_epoch().count());
> +        Codec<T>::encode_argument(writer, in.value);
> +        Codec<int64_t>::encode_argument(writer, in.when.time_since_epoch().count());
>      }
>  
> -    static void decode_argument(core::dbus::Message::Reader& out, com::ubuntu::location::Update<T>& in)
> +    static void decode_argument(Message::Reader& reader, com::ubuntu::location::Update<T>& in)
>      {
> -        Codec<T>::decode_argument(out, in.value);
> -        int64_t value;
> -        Codec<int64_t>::decode_argument(out, value);
> -        in.when = com::ubuntu::location::Clock::Timestamp(com::ubuntu::location::Clock::Duration(value));
> +        Codec<T>::decode_argument(reader, in.value);
> +        in.when = com::ubuntu::location::Clock::Timestamp(com::ubuntu::location::Clock::Duration(reader.pop_int64()));
>      }    
>  };
>  }
> 
> === added directory 'include/location_service/com/ubuntu/location/connectivity'
> === added file 'include/location_service/com/ubuntu/location/connectivity/bounded_integer.h'
> --- include/location_service/com/ubuntu/location/connectivity/bounded_integer.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/connectivity/bounded_integer.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,209 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_BOUNDED_INTEGER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_BOUNDED_INTEGER_H_
> +
> +#include <iostream>
> +#include <stdexcept>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +namespace connectivity
> +{
> +/**
> + * @brief A helper class to handle bounded integer values, with an optional domain
> + * for tagging domain-specific types.
> + */
> +template<typename Tag, int min, int max, int inv = min-1>
> +class BoundedInteger
> +{
> +public:
> +    static_assert(min < max, "min >= max");
> +
> +    /**
> +      * @brief Returns the invalid value for the specified range
> +      */
> +    inline static int invalid()
> +    {
> +        return inv;
> +    }
> +
> +    /**
> +     * @brief Access the minimum value of the integer.
> +     */
> +    inline static int minimum()
> +    {
> +        return min;
> +    }
> +
> +    /**
> +     * @brief Access the maximum value of the integer.
> +     */
> +    inline static int maximum()
> +    {
> +        return max;
> +    }
> +
> +    /**
> +     * @brief Returns max - min.
> +     */
> +    inline static int range()
> +    {
> +        return max - min;
> +    }
> +
> +    /**
> +     * @brief from_percent creates a new instance, mapping to the defined range of valid values.
> +     */
> +    inline static BoundedInteger<Tag, min, max, inv> from_percent(float percent)
> +    {
> +        // Capping to [0,1]
> +        percent = std::min<float>(1., std::max<float>(0., percent));
> +
> +        return BoundedInteger<Tag, min, max, inv>
> +        {
> +            static_cast<int>(minimum() + percent * range())
> +        };
> +    }
> +
> +    /**
> +     * @brief Constructs an invalid instance.
> +     */
> +    inline BoundedInteger() : value(min-1)
> +    {
> +    }
> +
> +    /**
> +     * @brief Constructs an instance from a raw value
> +     * @param value The raw value.
> +     * @throw std::runtime_error if value is not in [min, max].
> +     */
> +    inline explicit BoundedInteger(int value) : value(value)
> +    {
> +        if (value < min || value > max)
> +            throw std::runtime_error(
> +                    std::to_string(value) + " is not in " + "[" +
> +                    std::to_string(min) + ", " + std::to_string(max) + "]");
> +    }
> +
> +    /**
> +     * @brief Copy c'tor.
> +     * @param rhs The instance to copy from.
> +     */
> +    inline BoundedInteger(const BoundedInteger<Tag, min, max, inv>& rhs) : value(rhs.value)
> +    {
> +    }
> +
> +    /**
> +     * @brief Assignment operator.
> +     * @param rhs The instance to assign from.
> +     * @return A mutable reference to this instance.
> +     */
> +    inline BoundedInteger<Tag, min, max, inv>& operator=(const BoundedInteger<Tag, min, max, inv>& rhs)
> +    {
> +        value = rhs.value;
> +        return *this;
> +    }
> +
> +    /**
> +     * @brief Equality comparison operator.
> +     * @param rhs The instance to compare to.
> +     * @return true iff both instances' value are equal.
> +     */
> +    inline bool operator==(const BoundedInteger<Tag, min, max, inv>& rhs) const
> +    {
> +        return value == rhs.value;
> +    }
> +
> +    /**
> +     * @brief Implicit casting operator to a raw integer value.
> +     * @return The raw integer value.
> +     */
> +    inline operator int() const
> +    {
> +        return get();
> +    }
> +
> +    /**
> +     * @brief is_valid checks whether the contained value is in [min, max].
> +     * @return true iff the contained integer value is in [min, max].
> +     */
> +    inline bool is_valid() const
> +    {
> +        return min <= value && value <= max;
> +    }
> +
> +    /**
> +     * @brief Returns the raw integer value contained in this instance.
> +     * @throw std::runtime_error if is_valid() returns false.
> +     */
> +    inline int get() const
> +    {
> +        return value;
> +    }
> +
> +    /**
> +     * @brief Assigns a new raw integer value
> +     * @param new_value The new value.
> +     * @throw std::runtime_error if new_value is not in [min, max].
> +     */
> +    inline void set(int new_value)
> +    {
> +        if (new_value < min || new_value > max)
> +            throw std::runtime_error(
> +                    std::to_string(new_value) + " is not in " + "[" +
> +                    std::to_string(min) + ", " + std::to_string(max) + "]");
> +
> +        value = new_value;
> +    }
> +
> +    /** @brief Resets the instance to an invalid value. */
> +    inline void reset()
> +    {
> +        value = invalid();
> +    }
> +
> +    /**
> +     * @brief operator << pretty prints an instance of BoundedInteger.
> +     * @param out The stream to print to.
> +     * @param bi The instance to print.
> +     * @return The stream that has been printed to.
> +     */
> +    inline friend std::ostream& operator<<(std::ostream& out, const BoundedInteger<Tag, min, max, inv>& bi)
> +    {
> +        out << bi.value;
> +
> +        if (!bi.is_valid())
> +            out << " -> invalid";
> +
> +        return out;
> +    }
> +
> +private:
> +    int value;
> +};
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_BOUNDED_INTEGER_H_
> 
> === added file 'include/location_service/com/ubuntu/location/connectivity/manager.h'
> --- include/location_service/com/ubuntu/location/connectivity/manager.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/connectivity/manager.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,167 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.

Please update the copyright to 2014.

> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_MANAGER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_MANAGER_H_
> +
> +#include <com/ubuntu/location/connectivity/radio_cell.h>
> +#include <com/ubuntu/location/connectivity/wireless_network.h>
> +
> +#include <core/property.h>
> +
> +#include <memory>
> +#include <string>
> +#include <vector>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +namespace connectivity
> +{
> +/** @brief Enumerates all known system connectivity states. */
> +enum class State
> +{
> +    /** The state is unknown. */
> +    unknown,
> +    /** The system is not connected to any network. */
> +    none,
> +    /** The system is behind a captive portal and cannot reach the full internet. */
> +    portal,
> +    /**
> +     * The system is connected to a network, but does not appear to be able to reach
> +     * the full internet.
> +     */
> +    limited,
> +    /** The system is connected to a network, and appears to be able to reach the full internet. */
> +    full
> +};
> +
> +/**
> + * @brief The Manager class encapsulates access to network/radio information
> + */
> +class Manager
> +{
> +public:
> +    struct Errors
> +    {
> +        Errors() = delete;
> +        /**
> +         * @brief The ConnectivityManagementNotSupported struct is thrown if the underlying
> +         * platform does not provide support for connectivity mgmt.
> +         */
> +        struct ConnectivityManagementNotSupported : public std::runtime_error
> +        {
> +            ConnectivityManagementNotSupported()
> +                : std::runtime_error(
> +                      "Underlying platform does not provide support for connectivity mgmt.")
> +            {
> +            }
> +        };
> +    };
> +
> +    /** @cond */
> +    Manager(const Manager& rhs) = delete;
> +    virtual ~Manager() = default;
> +
> +    Manager& operator=(const Manager& rhs) = delete;
> +    bool operator==(const Manager& rhs) const = delete;
> +    /** @endcond */
> +
> +    /**
> +     * @brief Returns the getable/observable connectivity state of the system.
> +     *
> +     * Please note that this requires the underlying networking state to
> +     * support connectivity state tracking. Right now, e.g. NetworkManager needs
> +     * custom entries in /etc/NetworkManager/NetworkManager.conf to enable this
> +     * functionality.
> +     *
> +     */
> +    virtual const core::Property<State>& state() const = 0;
> +
> +    /**
> +     * @brief request_scan_for_wireless_networks schedules a scan for visible wireless networks.
> +     * @throws std::runtime_error to indicate issues arising from the underlying networking stack.
> +     *
> +     * Please note that the implementation is required to operate asynchronously. Results of the scan
> +     * are reported via emitting the changed() signal on the visible_wireless_networks() property.
> +     *
> +     * Please also note that calling this function is usually not required. The underlying
> +     * networking stack is updating the list of available wireless networks very frequently.
> +     * In addition, the results from scans requested by other system components are reported
> +     * to consumers of this API, too.
> +     *
> +     */
> +    virtual void request_scan_for_wireless_networks() = 0;
> +
> +    /**
> +     * @brief wireless_network_scan_finished is emitted when a scan for wireless networks ends.
> +     *
> +     * Please note that the signal may also be raised for scans that have been
> +     * initiated by other system components.
> +     *
> +     */
> +    virtual const core::Signal<>& wireless_network_scan_finished() const = 0;
> +
> +    /**
> +     * @brief wireless_network_added is emitted whenever a new wifi becomes visible.
> +     */
> +    virtual const core::Signal<WirelessNetwork::Ptr>& wireless_network_added() const = 0;
> +
> +    /**
> +     * @brief wireless_network_removed is emitted whenever a wifi disappears.
> +     */
> +    virtual const core::Signal<WirelessNetwork::Ptr>& wireless_network_removed() const = 0;
> +
> +    /**
> +     * @brief Enumerates all wireless networks visible to the device.
> +     */
> +    virtual void enumerate_visible_wireless_networks(const std::function<void(const WirelessNetwork::Ptr&)>&) const = 0;
> +
> +    /**
> +     * @brief connected_cell_added is emitted whenever the underlying modem connects to a new cell.
> +     */
> +    virtual const core::Signal<RadioCell::Ptr>& connected_cell_added() const = 0;
> +
> +    /**
> +     * @brief connected_cell_removed is emitted whenever the underlying modem disconnects from a cell.
> +     */
> +    virtual const core::Signal<RadioCell::Ptr>& connected_cell_removed() const = 0;
> +
> +    /**
> +     * @brief Enumerates all radio cells that the device is connected to.
> +     */
> +    virtual void enumerate_connected_radio_cells(const std::function<void(const RadioCell::Ptr&)>&) const = 0;
> +
> +protected:
> +    Manager() = default;
> +};
> +
> +/**
> + * @brief Provides access to a platform-specific implementation/instance of a connectivity manager.
> + * @throw Manager::Errors::ConnectivityManagementNotSupported.
> + * @return An instance of a connectivity manager.
> + */
> +const std::shared_ptr<Manager>& platform_default_manager();
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_MANAGER_H_
> 
> === added file 'include/location_service/com/ubuntu/location/connectivity/radio_cell.h'
> --- include/location_service/com/ubuntu/location/connectivity/radio_cell.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/connectivity/radio_cell.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,283 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *

Update the copyright to 2014.

> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_RADIO_CELL_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_RADIO_CELL_H_
> +
> +#include <com/ubuntu/location/connectivity/bounded_integer.h>
> +
> +#include <core/signal.h>
> +
> +#include <limits>
> +#include <memory>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +namespace connectivity
> +{
> +/** @brief Models a radio cell that one of the modems in the system is connected to. */
> +struct RadioCell
> +{
> +    /** @cond */
> +    typedef std::shared_ptr<RadioCell> Ptr;
> +    /** @endcond */
> +
> +    /** @brief Enumerates the known technologies. */
> +    enum class Type
> +    {
> +        unknown,
> +        gsm,
> +        umts,
> +        lte
> +    };
> +
> +    /** @cond */
> +    struct Mcc {};
> +    struct Mnc {};
> +    struct Lac {};
> +    struct Id {};
> +    struct Psc {};
> +    struct Pid {};
> +    struct Rss {};
> +    struct Asu {};
> +    struct Ta {};
> +
> +    template<int min, int max, int invalid = min-1>
> +    using MobileCountryCode = BoundedInteger<Mcc, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using MobileNetworkCode = BoundedInteger<Mnc, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using LocationAreaCode = BoundedInteger<Lac, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using TrackingAreaCode = BoundedInteger<Lac, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using CellId = BoundedInteger<Id, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using PrimaryScramblingCode = BoundedInteger<Psc, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using PhysicalId = BoundedInteger<Pid, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using ReceivedSignalStrength = BoundedInteger<Rss, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using ArbitraryStrengthUnit = BoundedInteger<Asu, min, max, invalid>;
> +    template<int min, int max, int invalid = min-1>
> +    using TimingAdvance = BoundedInteger<Ta, min, max, invalid>;
> +    /** @endcond */
> +
> +    /** @brief Models a GSM radio cell. */
> +    struct Gsm
> +    {
> +        /** 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
> +        typedef MobileCountryCode
> +        <
> +            0,
> +            999,
> +            std::numeric_limits<int>::max()
> +        > MCC;
> +        /** 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
> +        typedef MobileNetworkCode
> +        <
> +            0,
> +            999,
> +            std::numeric_limits<int>::max()
> +        > MNC;
> +        /** 16-bit Location Area Code, 0..65535, INT_MAX if unknown  */
> +        typedef LocationAreaCode
> +        <
> +            0,
> +            65535,
> +            std::numeric_limits<int>::max()
> +        > LAC;
> +        /** 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown  */
> +        typedef CellId
> +        <
> +            0,
> +            65535,
> +            std::numeric_limits<int>::max()
> +        > ID;
> +
> +        /** Valid values are (0-31, 99) as defined in TS 27.007 8.5 */
> +        typedef ArbitraryStrengthUnit
> +        <
> +            0,
> +            31,
> +            99
> +        > SignalStrength;
> +
> +        MCC mobile_country_code;
> +        MNC mobile_network_code;
> +        LAC location_area_code;
> +        ID id;
> +        SignalStrength strength;
> +    };
> +
> +    /** @brief Models a UMTS radio cell. */
> +    struct Umts
> +    {
> +        /** 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
> +        typedef MobileCountryCode
> +        <
> +            0,
> +            999,
> +            std::numeric_limits<int>::max()
> +        > MCC;
> +        /** 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
> +        typedef MobileNetworkCode
> +        <
> +            0,
> +            999,
> +            std::numeric_limits<int>::max()
> +        > MNC;
> +        /** 16-bit Location Area Code, 0..65535, INT_MAX if unknown  */
> +        typedef LocationAreaCode
> +        <
> +            0,
> +            65535,
> +            std::numeric_limits<int>::max()
> +        > LAC;
> +        /** 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown  */
> +        typedef CellId
> +        <
> +            0,
> +            268435455,
> +            std::numeric_limits<int>::max()
> +        > ID;
> +        /** Valid values are (0-31, 99) as defined in TS 27.007 8.5 */
> +        typedef ArbitraryStrengthUnit
> +        <
> +            0,
> +            31,
> +            99
> +        > SignalStrength;
> +
> +        MCC mobile_country_code;
> +        MNC mobile_network_code;
> +        LAC location_area_code;
> +        ID id;
> +        SignalStrength strength;
> +    };
> +
> +    /** @brief Models an LTE radio cell. */
> +    struct Lte
> +    {
> +        /** 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
> +        typedef MobileCountryCode
> +        <
> +            0,
> +            999,
> +            std::numeric_limits<int>::max()
> +        > MCC;
> +        /** 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
> +        typedef MobileNetworkCode
> +        <
> +            0,
> +            999,
> +            std::numeric_limits<int>::max()
> +        > MNC;
> +        /** 16-bit Tracking Area Code, 0..65535, INT_MAX if unknown  */
> +        typedef TrackingAreaCode
> +        <
> +            0,
> +            65535,
> +            std::numeric_limits<int>::max()
> +        > TAC;
> +        /** 28-bit Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown  */
> +        typedef CellId
> +        <
> +            0,
> +            268435455,
> +            std::numeric_limits<int>::max()
> +        > ID;
> +        /** Physical cell id, 0..503, INT_MAX if unknown */
> +        typedef PhysicalId
> +        <
> +            0,
> +            503,
> +            std::numeric_limits<int>::max()
> +        > PID;
> +        /** Valid values are (0-31, 99) as defined in TS 27.007 8.5 */
> +        typedef ArbitraryStrengthUnit
> +        <
> +            0,
> +            31,
> +            99
> +        > SignalStrength;
> +
> +        MCC mobile_country_code;
> +        MNC mobile_network_code;
> +        TAC tracking_area_code;
> +        ID id;
> +        PID physical_id;
> +        SignalStrength strength;
> +    };
> +
> +    RadioCell() = default;
> +    virtual ~RadioCell() = default;
> +
> +    RadioCell(const RadioCell& rhs) = delete;
> +    RadioCell& operator=(const RadioCell& rhs) = delete;
> +
> +    /** @brief Emitted when the cell details change. */
> +    virtual const core::Signal<>& changed() const = 0;
> +
> +    /** @brief Returns the type of the radio cell. */
> +    virtual Type type() const = 0;
> +
> +    /** @brief Returns GSM-specific details or throws std::runtime_error if this is not a GSM radiocell. */
> +    virtual const Gsm& gsm() const = 0;
> +
> +    /** @brief Returns UMTS-specific details or throws std::runtime_error if this is not a UMTS radiocell. */
> +    virtual const Umts& umts() const = 0;
> +
> +    /** @brief Returns LTE-specific details or throws std::runtime_error if this is not an LTE radiocell. */
> +    virtual const Lte& lte() const = 0;
> +};
> +
> +/** @brief Returns true iff lhs equals rhs. */
> +bool operator==(const RadioCell::Gsm& lhs, const RadioCell::Gsm& rhs);
> +
> +/** @brief Pretty-prints the given gsm details to the given output stream. */
> +std::ostream& operator<<(std::ostream& out, const RadioCell::Gsm& gsm);
> +
> +/** @brief Returns true iff lhs equals rhs. */
> +bool operator==(const RadioCell::Umts& lhs, const RadioCell::Umts& rhs);
> +
> +/** @brief Pretty-prints the given umts details to the given output stream. */
> +std::ostream& operator<<(std::ostream& out, const RadioCell::Umts& umts);
> +
> +/** @brief Returns true iff lhs equals rhs. */
> +bool operator==(const RadioCell::Lte& lhs, const RadioCell::Lte& rhs);
> +
> +/** @brief Pretty-prints the given gsm details to the given output stream. */
> +std::ostream& operator<<(std::ostream& out, const RadioCell::Lte& lte);
> +
> +/** @brief Returns true iff lhs equals rhs. */
> +bool operator==(const RadioCell& lhs, const RadioCell& rhs);
> +
> +/** @brief Pretty-prints the given cell to the given output stream. */
> +std::ostream& operator<<(std::ostream& out, const RadioCell& cell);
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_RADIO_CELL_H_
> +
> 
> === added file 'include/location_service/com/ubuntu/location/connectivity/wireless_network.h'
> --- include/location_service/com/ubuntu/location/connectivity/wireless_network.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/connectivity/wireless_network.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,117 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *

Update the copyright to 2014.

> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_WIRELESS_NETWORK_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_WIRELESS_NETWORK_H_
> +
> +#include <com/ubuntu/location/connectivity/bounded_integer.h>
> +
> +#include <core/property.h>
> +
> +#include <iosfwd>
> +#include <string>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +namespace connectivity
> +{
> +struct WirelessNetwork
> +{
> +    typedef std::shared_ptr<WirelessNetwork> Ptr;
> +
> +    /** @brief Enumerates all known operational modes of networks/aps. */
> +    enum class Mode
> +    {
> +        /** Mode is unknown. */
> +        unknown = 0,
> +        /** Indicates the object is part of an Ad-Hoc 802.11 network without a central coordinating access point. */
> +        adhoc = 1,
> +        /** The wireless device or access point is in infrastructure mode. */
> +        infrastructure = 2
> +    };
> +
> +    /** @cond */
> +    struct Tag
> +    {
> +        /** @brief Tags a frequency measurement for a wireless network. */
> +        struct Frequency {};
> +        /** @brief Tags the signal strength of a wireless network. */
> +        struct SignalStrength {};
> +    };
> +    /** @endcond */
> +
> +    /** Frequency that an individual AP operates on. */
> +    typedef BoundedInteger
> +    <
> +        Tag::Frequency,
> +        2412,
> +        5825
> +    > Frequency;
> +
> +    /** Strength of signal for an individual AP. */
> +    typedef BoundedInteger
> +    <
> +        Tag::SignalStrength,
> +        0,
> +        100
> +    > SignalStrength;
> +
> +    /** @cond */
> +    WirelessNetwork() = default;
> +    WirelessNetwork(const WirelessNetwork&) = delete;
> +    WirelessNetwork(WirelessNetwork&&) = delete;
> +
> +    virtual ~WirelessNetwork() = default;
> +
> +    WirelessNetwork& operator=(const WirelessNetwork&) = delete;
> +    WirelessNetwork& operator=(WirelessNetwork&&) = delete;
> +    /** @endcond */
> +
> +    /** @brief Timestamp when the network became visible. */
> +    virtual const core::Property<std::chrono::system_clock::time_point>& last_seen() const = 0;
> +
> +    /** @brief Returns the BSSID of the network */
> +    virtual const core::Property<std::string>& bssid() const = 0;
> +
> +    /** @brief Returns the SSID of the network. */
> +    virtual const core::Property<std::string>& ssid() const = 0;
> +
> +    /** @brief Returns the mode of the network. */
> +    virtual const core::Property<Mode>& mode() const = 0;
> +
> +    /** @brief Returns the frequency that the network/AP operates upon. */
> +    virtual const core::Property<Frequency>& frequency() const = 0;
> +
> +    /** @brief Returns the signal quality of the network/AP in percent. */
> +    virtual const core::Property<SignalStrength>& signal_strength() const = 0;
> +};
> +
> +/** @brief Pretty-prints the given mode to the given output stream. */
> +std::ostream& operator<<(std::ostream& out, WirelessNetwork::Mode mode);
> +
> +/** @brief Pretty-prints the given wireless network to the given output stream. */
> +std::ostream& operator<<(std::ostream& out, const WirelessNetwork& wifi);
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_WIRELESS_NETWORK_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/criteria.h'
> --- include/location_service/com/ubuntu/location/criteria.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/criteria.h	2014-06-24 16:02:38 +0000
> @@ -18,16 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CRITERIA_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CRITERIA_H_
>  
> -#include "com/ubuntu/location/accuracy.h"
> -#include "com/ubuntu/location/heading.h"
> -#include "com/ubuntu/location/velocity.h"
> -#include "com/ubuntu/location/wgs84/altitude.h"
> -#include "com/ubuntu/location/wgs84/latitude.h"
> -#include "com/ubuntu/location/wgs84/longitude.h"
> -
> -#include <limits>
> -#include <ostream>
> -#include <stdexcept>
> +#include <com/ubuntu/location/optional.h>
> +#include <com/ubuntu/location/units/units.h>
>  
>  namespace com
>  {
> @@ -35,22 +27,40 @@
>  {
>  namespace location
>  {
> +/**
> + * @brief Summarizes criteria of a client session with respect to functionality
> + * and accuracy for position, velocity and heading measurements.
> + */
>  struct Criteria
>  {
> -    Criteria() : latitude_accuracy(),
> -                 longitude_accuracy(),
> -                 altitude_accuracy(),
> -                 velocity_accuracy(),
> -                 heading_accuracy()
> -    {
> -    }
> -    
> -    Accuracy<wgs84::Latitude> latitude_accuracy;
> -    Accuracy<wgs84::Longitude> longitude_accuracy;
> -    Accuracy<wgs84::Altitude> altitude_accuracy;
> -    Accuracy<Velocity> velocity_accuracy;
> -    Accuracy<Heading> heading_accuracy;
> +    /**
> +     * @brief satisfies checks whether this instance also satisfies another criteria instance.
> +     * @param rhs The other criteria instance
> +     * @return true iff this instance also satisfies the other instance, else false.
> +     */
> +    bool satisfies(const Criteria& rhs) const;
> +
> +    struct Requires
> +    {
> +        bool position = true; ///< The client needs position measurements.
> +        bool altitude = false; ///< The client needs altitude measurements.
> +        bool velocity = false; ///< The client needs velocity measurments.
> +        bool heading = false; ///< The client needs heading measurements.
> +    } requires = Requires{};
> +
> +    struct Accuracy
> +    {
> +        units::Quantity<units::Length> horizontal = 3000 * units::Meters; ///< The client requires measurements of at least this horizontal accuracy.
> +        Optional<units::Quantity<units::Length>> vertical; ///< The client requires measurements of at least this vertical accuracy.
> +        Optional<units::Quantity<units::Velocity>> velocity; ///< The client requires measurements of at least this velocity accuracy.
> +        Optional<units::Quantity<units::PlaneAngle>> heading; ///< The client requires measurements of at least this heading accuracy.
> +    } accuracy = Accuracy{};
>  };
> +
> +/**
> + * @brief operator + merges lhs and rhs such that satisfying the new criteria satisfies lhs and rhs.
> + */
> +Criteria operator+(const Criteria& lhs, const Criteria& rhs);
>  }
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/default_provider_selection_policy.h'
> --- include/location_service/com/ubuntu/location/default_provider_selection_policy.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/default_provider_selection_policy.h	2014-06-24 16:02:38 +0000
> @@ -18,7 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_DEFAULT_PROVIDER_SELECTION_POLICY_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_DEFAULT_PROVIDER_SELECTION_POLICY_H_
>  
> -#include "com/ubuntu/location/provider_selection_policy.h"
> +#include <com/ubuntu/location/provider_selection_policy.h>
>  
>  namespace com
>  {
> @@ -32,21 +32,21 @@
>      DefaultProviderSelectionPolicy();
>      ~DefaultProviderSelectionPolicy() noexcept;
>      
> -    ProviderSelection determine_provider_selection_from_set_for_criteria(
> +    ProviderSelection determine_provider_selection_for_criteria(
>          const Criteria& criteria,
> -        const std::set<Provider::Ptr>& providers);
> +        const ProviderEnumerator& enumerator);
>  
>      Provider::Ptr determine_position_updates_provider(
>          const Criteria& criteria,
> -        const std::set<Provider::Ptr>& providers);
> +        const ProviderEnumerator& enumerator);
>  
>      Provider::Ptr determine_heading_updates_provider(
>          const Criteria& criteria,
> -        const std::set<Provider::Ptr>& providers);
> +        const ProviderEnumerator& enumerator);
>  
>      Provider::Ptr determine_velocity_updates_provider(
>          const Criteria& criteria,
> -        const std::set<Provider::Ptr>& providers);
> +        const ProviderEnumerator& enumerator);
>  };
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/engine.h'
> --- include/location_service/com/ubuntu/location/engine.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/engine.h	2014-06-24 16:02:38 +0000
> @@ -18,10 +18,16 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_ENGINE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_ENGINE_H_
>  
> -#include "com/ubuntu/location/criteria.h"
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/provider_selection_policy.h"
> -
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/provider_enumerator.h>
> +#include <com/ubuntu/location/provider_selection.h>
> +#include <com/ubuntu/location/satellite_based_positioning_state.h>
> +#include <com/ubuntu/location/space_vehicle.h>
> +#include <com/ubuntu/location/wifi_and_cell_reporting_state.h>
> +
> +#include <core/property.h>
> +
> +#include <mutex>
>  #include <set>
>  
>  namespace com
> @@ -30,26 +36,118 @@
>  {
>  namespace location
>  {
> -class Engine
> +struct Criteria;
> +class ProviderSelectionPolicy;
> +/**
> + * @brief The Engine class encapsulates a positioning engine, relying on a set
> + * of providers and reporters to acquire and publish location information.
> + */
> +class Engine : public ProviderEnumerator
>  {
>  public:
>      typedef std::shared_ptr<Engine> Ptr;
>  
> -    Engine(const std::set<Provider::Ptr>& initial_providers,
> -           const ProviderSelectionPolicy::Ptr& provider_selection_policy);
> +    /**
> +     * @brief The State enum models the current state of the engine
> +     */
> +    enum class Status
> +    {
> +        off, ///< The engine is currently offline.
> +        on, ///< The engine and providers are powered on but not navigating.
> +        active ///< The engine and providers are powered on and navigating.
> +    };
> +
> +    /**
> +     * @brief The Configuration struct summarizes the state of the engine.
> +     */
> +    struct Configuration
> +    {
> +        /** Setable/getable/observable property for the satellite based positioning state. */
> +        core::Property<SatelliteBasedPositioningState> satellite_based_positioning_state
> +        {
> +            SatelliteBasedPositioningState::on
> +        };
> +        /** Setable/getable/observable property for the satellite based positioning state. */
> +        core::Property<WifiAndCellIdReportingState> wifi_and_cell_id_reporting_state
> +        {
> +            WifiAndCellIdReportingState::off
> +        };
> +        /** Setable/getable/observable property for the overall engine state. */
> +        core::Property<Engine::Status> engine_state
> +        {
> +            Engine::Status::on
> +        };
> +    };
> +
> +    /** @brief Summarizes all updates delivered via the engine. */
> +    struct Updates
> +    {
> +        /** The current best known reference location */
> +        core::Property<Update<Position>> reference_location{};
> +        /** The current best known velocity estimate. */
> +        core::Property<Update<Velocity>> reference_velocity{};
> +        /** The current best known heading estimate. */
> +        core::Property<Update<Heading>> reference_heading{};
> +        /** The current set of visible SpaceVehicles. */
> +        core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>> visible_space_vehicles{};
> +    };
> +
> +    Engine(const std::shared_ptr<ProviderSelectionPolicy>& provider_selection_policy);
>      Engine(const Engine&) = delete;
>      Engine& operator=(const Engine&) = delete;
> -    virtual ~Engine() = default;
> +    virtual ~Engine();
>  
> +    /**
> +     * @brief Calculates a set of providers that satisfies the given criteria.
> +     * @param [in] criteria The criteria to be satisfied by the returned provider selection.
> +     * @return A provider selection that satisfies the given criteria.
> +     */
>      virtual ProviderSelection determine_provider_selection_for_criteria(const Criteria& criteria);
>  
> +    /**
> +     * @brief Checks if the engine knows about a specific provider.
> +     * @return True iff the engine knows about the provider.
> +     */
>      virtual bool has_provider(const Provider::Ptr& provider) noexcept;
> +
> +    /**
> +     * @brief Makes a provider known to the engine.
> +     * @param provider The new provider.
> +     */
>      virtual void add_provider(const Provider::Ptr& provider);
> +
> +    /**
> +     * @brief Removes a provider from the engine.
> +     * @param provider The provider to be removed.
> +     */
>      virtual void remove_provider(const Provider::Ptr& provider) noexcept;
>  
> +    /**
> +     * @brief Iterates all known providers and invokes the provided enumerator for each of them.
> +     * @param enumerator The functor to be invoked for each provider.
> +     */
> +    virtual void for_each_provider(const std::function<void(const Provider::Ptr&)>& enumerator) const noexcept;
> +
> +    /** @brief The engine's configuration. */
> +    Configuration configuration;
> +
> +    /** @brief All updates distributed via the engine. */
> +    Updates updates;
> +
>  private:
> -    std::set<Provider::Ptr> providers;
> -    ProviderSelectionPolicy::Ptr provider_selection_policy;
> +    struct ProviderConnections
> +    {
> +        core::ScopedConnection reference_location_updates;
> +        core::ScopedConnection reference_velocity_updates;
> +        core::ScopedConnection reference_heading_updates;
> +        core::ScopedConnection wifi_and_cell_id_reporting_state_updates;
> +        core::ScopedConnection space_vehicle_visibility_updates;
> +        core::ScopedConnection provider_position_updates;
> +    };
> +
> +    mutable std::mutex guard;
> +    std::map<Provider::Ptr, ProviderConnections> providers;
> +    std::shared_ptr<ProviderSelectionPolicy> provider_selection_policy;
>  };
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/heading.h'
> --- include/location_service/com/ubuntu/location/heading.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/heading.h	2014-06-24 16:02:38 +0000
> @@ -18,12 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_HEADING_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_HEADING_H_
>  
> -#include "com/ubuntu/location/accuracy.h"
> -#include "com/ubuntu/location/units/units.h"
> -
> -#include <limits>
> -#include <ostream>
> -#include <stdexcept>
> +#include <com/ubuntu/location/units/units.h>
>  
>  namespace com
>  {
> @@ -31,74 +26,8 @@
>  {
>  namespace location
>  {
> -struct Heading
> -{
> -    typedef units::PlaneAngle Unit;
> -    typedef units::Quantity<Unit> Quantity;
> -
> -    static const Quantity& min()
> -    {
> -        static const auto instance = Heading::Quantity::from_value(0.);
> -        return instance;
> -    }
> -    static const Quantity& max()
> -    {
> -        static const auto instance = Heading::Quantity::from_value(360.);
> -        return instance;
> -    }
> -
> -    Heading(const Quantity& value = Quantity()) : value(value)
> -    {
> -        if (value < min())
> -            throw std::out_of_range("");
> -        if (value > max())
> -            throw std::out_of_range("");
> -    }
> -
> -    bool operator==(const Heading& rhs) const
> -    {
> -        return value == rhs.value;
> -    }
> -
> -    bool operator!=(const Heading& rhs) const
> -    {
> -        return value != rhs.value;
> -    }
> -
> -    Quantity value;
> -};
> -
> -inline std::ostream& operator<<(std::ostream& out, const Heading& heading)
> -{
> -    out << "Heading(" << heading.value << ")";
> -    return out;
> -}
> -
> -template<>
> -struct AccuracyTraits<Heading>
> -{
> -    static AccuracyLevel classify(const Heading& h)
> -    {
> -        static const auto half = 0.5 * Heading::max();
> -        if(h.value > half)
> -            return AccuracyLevel::worst;
> -
> -        if(h.value < half)
> -            return AccuracyLevel::best;
> -
> -        return AccuracyLevel::worst;
> -    }
> -
> -    static Accuracy<Heading> best()
> -    {
> -        return Accuracy<Heading>{Heading{Heading::min()}};
> -    }
> -
> -    static Accuracy<Heading> worst()
> -    {
> -        return Accuracy<Heading>{Heading{Heading::max()}};
> -    }
> -};
> +/** Heading is measured in ° deviation from true north. */
> +typedef units::Quantity<units::PlaneAngle> Heading;
>  }
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/logging.h'
> --- include/location_service/com/ubuntu/location/logging.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/logging.h	2014-06-24 16:02:38 +0000
> @@ -19,6 +19,7 @@
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_LOGGING_H_
>  
>  #include <glog/logging.h>
> +#include <glog/vlog_is_on.h>
>  
>  #endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_LOGGING_H_
>  
> 
> === added file 'include/location_service/com/ubuntu/location/optional.h'
> --- include/location_service/com/ubuntu/location/optional.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/optional.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *

Update the copyright to 2014.

> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_OPTIONAL_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_OPTIONAL_H_
> +
> +#include <boost/optional.hpp>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +template<typename T>
> +using Optional = boost::optional<T>;
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_OPTIONAL_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/position.h'
> --- include/location_service/com/ubuntu/location/position.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/position.h	2014-06-24 16:02:38 +0000
> @@ -18,9 +18,11 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_POSITION_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_POSITION_H_
>  
> -#include "com/ubuntu/location/wgs84/altitude.h"
> -#include "com/ubuntu/location/wgs84/latitude.h"
> -#include "com/ubuntu/location/wgs84/longitude.h"
> +#include <com/ubuntu/location/wgs84/altitude.h>
> +#include <com/ubuntu/location/wgs84/latitude.h>
> +#include <com/ubuntu/location/wgs84/longitude.h>
> +
> +#include <com/ubuntu/location/optional.h>
>  
>  #include <bitset>
>  #include <ostream>
> @@ -31,54 +33,33 @@
>  {
>  namespace location
>  {
> -class Position
> +/**
> + * @brief The Position struct models a position in the wgs84 coordinate system.
> + */
> +struct Position
>  {
> -  public:
> -    enum Flag
> +    struct Accuracy
>      {
> -        latitude_flag = 0,
> -        longitude_flag = 1,
> -        altitude_flag = 2
> +        typedef units::Quantity<units::Length> Horizontal;
> +        typedef units::Quantity<units::Length> Vertical;
> +
> +        Optional<Horizontal> horizontal{};
> +        Optional<Vertical> vertical{};
>      };
>  
> -    typedef std::bitset<3> Flags;
> -
> -    Position();    
> -    Position(
> -        const wgs84::Latitude& latitude,
> -        const wgs84::Longitude& longitude);
> -    Position(
> -        const wgs84::Latitude& latitude,
> -        const wgs84::Longitude& longitude,
> -        const wgs84::Altitude& altitude);
> +    Position() = default;
> +    Position(const wgs84::Latitude&, const wgs84::Longitude&);
> +    Position(const wgs84::Latitude&, const wgs84::Longitude&, const wgs84::Altitude&);
> +    Position(const wgs84::Latitude&, const wgs84::Longitude&, const wgs84::Altitude&, const units::Quantity<units::Length>& hor_acc);
> +    Position(const wgs84::Latitude&, const wgs84::Longitude&, const wgs84::Altitude&, const units::Quantity<units::Length>& hor_acc, const units::Quantity<units::Length>& ver_acc);
>  
>      bool operator==(const Position& rhs) const;
>      bool operator!=(const Position& rhs) const;
>  
> -    const Flags& flags() const;
> -
> -    bool has_latitude() const;
> -    Position& latitude(const wgs84::Latitude& lat);
> -    const wgs84::Latitude& latitude() const;
> -
> -    bool has_longitude() const;
> -    Position& longitude(const wgs84::Longitude& lon);
> -    const wgs84::Longitude& longitude() const;
> -
> -    bool has_altitude() const;
> -    Position& altitude(const wgs84::Altitude& alt);
> -    const wgs84::Altitude& altitude() const;
> -
> -  private:
> -    template<typename> friend struct Codec;
> -    
> -    struct
> -    {
> -        Flags flags;
> -        wgs84::Latitude latitude;
> -        wgs84::Longitude longitude;
> -        wgs84::Altitude altitude;
> -    } fields;
> +    wgs84::Latitude latitude = wgs84::Latitude{};
> +    wgs84::Longitude longitude = wgs84::Longitude{};
> +    Optional<wgs84::Altitude> altitude = Optional<wgs84::Altitude>{};
> +    Accuracy accuracy{};
>  };
>  
>  std::ostream& operator<<(std::ostream& out, const Position& position);
> 
> === modified file 'include/location_service/com/ubuntu/location/provider.h'
> --- include/location_service/com/ubuntu/location/provider.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/provider.h	2014-06-24 16:02:38 +0000
> @@ -18,12 +18,16 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDER_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDER_H_
>  
> -#include "com/ubuntu/location/channel.h"
> -#include "com/ubuntu/location/criteria.h"
> -#include "com/ubuntu/location/heading.h"
> -#include "com/ubuntu/location/position.h"
> -#include "com/ubuntu/location/update.h"
> -#include "com/ubuntu/location/velocity.h"
> +#include <com/ubuntu/location/criteria.h>
> +#include <com/ubuntu/location/heading.h>
> +#include <com/ubuntu/location/position.h>
> +#include <com/ubuntu/location/space_vehicle.h>
> +#include <com/ubuntu/location/update.h>
> +#include <com/ubuntu/location/velocity.h>
> +#include <com/ubuntu/location/wifi_and_cell_reporting_state.h>
> +
> +#include <core/property.h>
> +#include <core/signal.h>
>  
>  #include <atomic>
>  #include <bitset>
> @@ -35,97 +39,125 @@
>  {
>  namespace location
>  {
> +/**
> + * @brief The Provider class is the abstract base of all positioning providers.
> + */
>  class Provider
>  {
>  public:
>      typedef std::shared_ptr<Provider> Ptr;
>  
> -    enum class Feature : std::size_t
> -    {
> -        position,
> -        velocity,
> -        heading
> -    };
> -
> -    typedef std::bitset<3> FeatureFlags;
> -
> -    enum class Requirement : std::size_t
> -    {
> -        satellites,
> -        cell_network,
> -        data_network,
> -        monetary_spending
> -    };
> -
> -    typedef std::bitset<4> RequirementFlags;
> -
> +    /**
> +     * @brief Enumerates the known features that can be supported by providers.
> +     */
> +    enum class Features : std::size_t
> +    {
> +        none = 0, ///< The provider does not support any feature.
> +        position = 1 << 0, ///< The provider features position updates.
> +        velocity = 1 << 1, ///< The provider features velocity updates.
> +        heading = 1 << 2 ///< The provider features heading updates.
> +    };    
> +
> +    /**
> +     * @brief Enumerates the requirements of a provider implementation.
> +     */
> +    enum class Requirements : std::size_t
> +    {
> +        none = 0, ///< The provider does not require anything.
> +        satellites = 1 << 0, ///< The provider requires satellites to be visible.
> +        cell_network = 1 << 1, ///< The provider requires a cell-network to work correctly.
> +        data_network = 1 << 2, ///< The provider requires a data-network to work correctly.
> +        monetary_spending = 1 << 3 ///< Using the provider results in monetary cost.
> +    };
> +
> +    /**
> +     * @brief Facade for controlling the state of position/heading/velocity updates.
> +     *
> +     * Multiple observers can request state changes for updates. This class ensures
> +     * that the specific updates are started and stopped if at least one observer
> +     * requests them and stopped when the last observer issues a stop request.
> +     */
>      class Controller
>      {
>      public:
>          typedef std::shared_ptr<Controller> Ptr;
>  
> -        template<typename T> 
> -        class Cache
> -        {
> -          public:
> -            Cache() : d{ T{}, false }
> -            {
> -            }
> -            const T& value() const { return d.value; }
> -            void update(const T& new_value) { d.value = new_value; d.is_valid = true; }
> -            bool is_valid() const { return d.is_valid; }
> -            void invalidate() { d.is_valid = false; }
> -
> -          private:
> -            struct
> -            {
> -                T value;
> -                bool is_valid;
> -            } d;
> -        };
> -
>          virtual ~Controller() = default;
>          Controller(const Controller&) = delete;
>          Controller& operator=(const Controller&) = delete;
>  
> +        /**
> +         * @brief Request to start position updates if not already running.
> +         */
>          virtual void start_position_updates();
> +
> +        /**
> +         * @brief Request to stop position updates. Only stops the provider when the last observer calls this function.
> +         */
>          virtual void stop_position_updates();
> +
> +        /**
> +         * @brief Checks if position updates are currently running.
> +         * @return true iff position updates are currently running.
> +         */
>          bool are_position_updates_running() const;
>  
> +        /**
> +         * @brief Request to start heading updates if not already running.
> +         */
>          virtual void start_heading_updates();
> +
> +        /**
> +         * @brief Request to stop heading updates. Only stops the provider when the last observer calls this function.
> +         */
>          virtual void stop_heading_updates();
> +
> +        /**
> +         * @brief Checks if position updates are currently running.
> +         * @return true iff position updates are currently running.
> +         */
>          bool are_heading_updates_running() const;
>  
> +        /**
> +         * @brief Request to start velocity updates if not already running.
> +         */
>          virtual void start_velocity_updates();
> +
> +        /**
> +         * @brief Request to stop velocity updates. Only stops the provider when the last observer calls this function.
> +         */
>          virtual void stop_velocity_updates();
> +
> +        /**
> +         * @brief Checks if velocity updates are currently running.
> +         * @return true iff velocity updates are currently running.
> +         */
>          bool are_velocity_updates_running() const;
>  
> -        const Cache<Update<Position>>& cached_position_update() const;
> -        const Cache<Update<Heading>>& cached_heading_update() const;
> -        const Cache<Update<Velocity>>& cached_velocity_update() const;
> -
>      protected:
>          friend class Provider;
>          explicit Controller(Provider& instance);
>  
>      private:
> -        void on_position_updated(const Update<Position>& position);
> -        void on_velocity_updated(const Update<Velocity>& velocity);
> -        void on_heading_updated(const Update<Heading>& heading);
> -
>          Provider& instance;
>          std::atomic<int> position_updates_counter;
>          std::atomic<int> heading_updates_counter;
>          std::atomic<int> velocity_updates_counter;
> -        ScopedChannelConnection position_update_connection;
> -        ScopedChannelConnection velocity_update_connection;
> -        ScopedChannelConnection heading_update_connection;
> -        struct
> -        {
> -            Cache<Update<Position>> position;
> -            Cache<Update<Velocity>> velocity;
> -            Cache<Update<Heading>> heading;            
> -        } cached;
> +    };
> +
> +    /**
> +     * @brief Wraps all updates that can be delivered by a provider.
> +     */
> +    struct Updates
> +    {
> +        /** Position updates. */
> +        core::Signal<Update<Position>> position;
> +        /** Heading updates. */
> +        core::Signal<Update<Heading>> heading;
> +        /** Velocity updates. */
> +        core::Signal<Update<Velocity>> velocity;
> +        /** Space vehicle visibility updates. */
> +        core::Signal<Update<std::set<SpaceVehicle>>> svs;
>      };
>  
>      virtual ~Provider() = default;
> @@ -133,43 +165,114 @@
>      Provider(const Provider&) = delete;
>      Provider& operator=(const Provider&) = delete;
>  
> +    /**
> +     * @brief Provides non-mutable access to this provider's updates.
> +     * @return A non-mutable reference to the updates.
> +     */
> +    virtual const Updates& updates() const;
> +
> +    /**
> +     * @brief Access to the controller facade of this provider instance.
> +     */
>      virtual const Controller::Ptr& state_controller() const;
>  
> -    virtual ChannelConnection subscribe_to_position_updates(std::function<void(const Update<Position>&)> f);
> -    virtual ChannelConnection subscribe_to_heading_updates(std::function<void(const Update<Heading>&)> f);
> -    virtual ChannelConnection subscribe_to_velocity_updates(std::function<void(const Update<Velocity>&)> f);
> -
> -    virtual bool supports(const Feature& f) const;
> -    virtual bool requires(const Requirement& r) const;
> -
> -    virtual bool matches_criteria(const Criteria&);
> -    
> +    /**
> +     * @brief Checks if the provider supports a specific feature.
> +     * @param f Feature to test for
> +     * @return true iff the provider supports the feature.
> +     */
> +    virtual bool supports(const Features& f) const;
> +
> +    /**
> +     * @brief Checks if the provider has got a specific requirement.
> +     * @param r Requirement to test for.
> +     * @return true iff the provider has the specific requirement.
> +     */
> +    virtual bool requires(const Requirements& r) const;
> +
> +    /**
> +     * @brief Checks if a provider satisfies a set of accuracy criteria.
> +     * @param [in] criteria The criteria to check.
> +     * @return true iff the provider satisfies the given criteria.
> +     */
> +    virtual bool matches_criteria(const Criteria& criteria);
> +
> +    /**
> +     * @brief Called by the engine whenever the wifi and cell ID reporting state changes.
> +     * @param state The new state.
> +     */
> +    virtual void on_wifi_and_cell_reporting_state_changed(WifiAndCellIdReportingState state);
> +
> +    /**
> +     * @brief Called by the engine whenever the reference location changed.
> +     * @param position The new reference location.
> +     */
> +    virtual void on_reference_location_updated(const Update<Position>& position);
> +
> +    /**
> +     * @brief Called by the engine whenever the reference velocity changed.
> +     * @param velocity The new reference velocity.
> +     */
> +    virtual void on_reference_velocity_updated(const Update<Velocity>& velocity);
> +
> +    /**
> +     * @brief Called by the engine whenever the reference heading changed.
> +     * @param heading The new reference heading.
> +     */
> +    virtual void on_reference_heading_updated(const Update<Heading>& heading);
> +
>  protected:
>      explicit Provider(
> -        const FeatureFlags& feature_flags = FeatureFlags(),
> -        const RequirementFlags& requirement_flags = RequirementFlags());
> +        const Features& features = Features::none,
> +        const Requirements& requirements = Requirements::none);
>  
> -    void deliver_position_updates(const Update<Position>& update);
> -    void deliver_heading_updates(const Update<Heading>& update);
> -    void deliver_velocity_updates(const Update<Velocity>& update);
> +    virtual Updates& mutable_updates();
>      
> +    /**
> +     * @brief Implementation-specific, empty by default.
> +     */
>      virtual void start_position_updates();
> +
> +    /**
> +     * @brief Implementation-specific, empty by default.
> +     */
>      virtual void stop_position_updates();
>  
> +    /**
> +     * @brief Implementation-specific, empty by default.
> +     */
>      virtual void start_heading_updates();
> +
> +    /**
> +     * @brief Implementation-specific, empty by default.
> +     */
>      virtual void stop_heading_updates();
>  
> +    /**
> +     * @brief Implementation-specific, empty by default.
> +     */
>      virtual void start_velocity_updates();
> +
> +    /**
> +     * @brief Implementation-specific, empty by default.
> +     */
>      virtual void stop_velocity_updates();
>  
>  private:
> -    FeatureFlags feature_flags;
> -    RequirementFlags requirement_flags;
> -    Channel<Update<Position>> position_updates_channel;
> -    Channel<Update<Heading>> heading_updates_channel;
> -    Channel<Update<Velocity>> velocity_updates_channel;
> -    Controller::Ptr controller;
> +    struct
> +    {
> +        Features features = Features::none;
> +        Requirements requirements = Requirements::none;
> +        Updates updates;
> +        Controller::Ptr controller = Controller::Ptr{};
> +    } d;
>  };
> +
> +Provider::Features operator|(Provider::Features lhs, Provider::Features rhs);
> +Provider::Features operator&(Provider::Features lhs, Provider::Features rhs);
> +
> +Provider::Requirements operator|(Provider::Requirements lhs, Provider::Requirements rhs);
> +Provider::Requirements operator&(Provider::Requirements lhs, Provider::Requirements rhs);
>  }
>  }
>  }
> 
> === added file 'include/location_service/com/ubuntu/location/provider_enumerator.h'
> --- include/location_service/com/ubuntu/location/provider_enumerator.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/provider_enumerator.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *

Update the copyright to 2014.

> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_PROVIDER_ENUMERATOR_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_PROVIDER_ENUMERATOR_H_
> +
> +#include <functional>
> +#include <memory>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +class Provider;
> +class ProviderEnumerator
> +{
> +public:
> +    ProviderEnumerator(const ProviderEnumerator&) = delete;
> +    virtual ~ProviderEnumerator() = default;
> +
> +    ProviderEnumerator& operator=(const ProviderEnumerator&) = delete;
> +    bool operator==(const ProviderEnumerator&) const = delete;
> +
> +    virtual void for_each_provider(const std::function<void(const std::shared_ptr<Provider>&)>&) const = 0;
> +
> +protected:
> +    ProviderEnumerator() = default;
> +};
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_PROVIDER_ENUMERATOR_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/provider_factory.h'
> --- include/location_service/com/ubuntu/location/provider_factory.h	2013-05-29 06:04:02 +0000
> +++ include/location_service/com/ubuntu/location/provider_factory.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDER_FACTORY_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDER_FACTORY_H_
>  
> -#include "com/ubuntu/location/configuration.h"
> -#include "com/ubuntu/location/provider.h"
> +#include <com/ubuntu/location/configuration.h>
> +#include <com/ubuntu/location/provider.h>
>  
>  #include <functional>
>  #include <map>
> @@ -57,7 +57,7 @@
>      ProviderFactory& operator=(const ProviderFactory&) = delete;
>  
>      std::mutex guard;
> -    std::map<std::string, Factory> factory_store;    
> +    std::map<std::string, Factory> factory_store;
>  };
>  }
>  }
> 
> === added file 'include/location_service/com/ubuntu/location/provider_selection.h'
> --- include/location_service/com/ubuntu/location/provider_selection.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/provider_selection.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,62 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *

Update the copyright to 2014.

> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_PROVIDER_SELECTION_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_PROVIDER_SELECTION_H_
> +
> +#include <com/ubuntu/location/provider.h>
> +
> +#include <memory>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +struct ProviderSelection
> +{
> +    inline Provider::Features to_feature_flags() const
> +    {
> +        Provider::Features flags = Provider::Features::none;
> +
> +        if (position_updates_provider)
> +            flags = flags | Provider::Features::position;
> +        if (heading_updates_provider)
> +            flags = flags | Provider::Features::heading;
> +        if(velocity_updates_provider)
> +            flags = flags | Provider::Features::velocity;
> +
> +        return flags;
> +    }
> +
> +    std::shared_ptr<Provider> position_updates_provider;
> +    std::shared_ptr<Provider> heading_updates_provider;
> +    std::shared_ptr<Provider> velocity_updates_provider;
> +};
> +
> +inline bool operator==(const ProviderSelection& lhs, const ProviderSelection& rhs)
> +{
> +    return lhs.position_updates_provider == rhs.position_updates_provider &&
> +            lhs.heading_updates_provider == rhs.heading_updates_provider &&
> +            lhs.velocity_updates_provider == rhs.velocity_updates_provider;
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_PROVIDER_SELECTION_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/provider_selection_policy.h'
> --- include/location_service/com/ubuntu/location/provider_selection_policy.h	2013-06-10 11:10:00 +0000
> +++ include/location_service/com/ubuntu/location/provider_selection_policy.h	2014-06-24 16:02:38 +0000
> @@ -18,7 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_PROVIDER_SELECTION_POLICY_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_PROVIDER_SELECTION_POLICY_H_
>  
> -#include "com/ubuntu/location/provider.h"
> +#include <com/ubuntu/location/provider_enumerator.h>
> +#include <com/ubuntu/location/provider_selection.h>
>  
>  #include <memory>
>  
> @@ -29,52 +30,25 @@
>  namespace location
>  {
>  struct Criteria;
> -
> -struct ProviderSelection
> -{
> -    ProviderSelection(const Provider::Ptr position = Provider::Ptr{},
> -                      const Provider::Ptr heading = Provider::Ptr{},
> -                      const Provider::Ptr velocity = Provider::Ptr{}) : position_updates_provider(position),
> -                                                      heading_updates_provider(heading),
> -                                                      velocity_updates_provider(velocity)
> -    {
> -    }
> -    
> -    Provider::FeatureFlags to_feature_flags() const
> -    {
> -        Provider::FeatureFlags flags;
> -        flags.set(static_cast<std::size_t>(Provider::Feature::position), static_cast<bool>(position_updates_provider));
> -        flags.set(static_cast<std::size_t>(Provider::Feature::heading), static_cast<bool>(heading_updates_provider));
> -        flags.set(static_cast<std::size_t>(Provider::Feature::velocity), static_cast<bool>(velocity_updates_provider));
> -
> -        return flags;
> -    }
> -
> -    Provider::Ptr position_updates_provider;
> -    Provider::Ptr heading_updates_provider;
> -    Provider::Ptr velocity_updates_provider;
> -};
> -
> -inline bool operator==(const ProviderSelection& lhs, const ProviderSelection& rhs)
> -{
> -    return lhs.position_updates_provider == rhs.position_updates_provider &&
> -            lhs.heading_updates_provider == rhs.heading_updates_provider &&
> -            lhs.velocity_updates_provider == rhs.velocity_updates_provider;
> -}
> +class Engine;
>  
>  class ProviderSelectionPolicy
>  {
>  public:
>      typedef std::shared_ptr<ProviderSelectionPolicy> Ptr;
>  
> +    static const Provider::Ptr& null_provider();
> +
> +    ProviderSelectionPolicy(const ProviderSelectionPolicy&) = delete;
> +    ProviderSelectionPolicy& operator=(const ProviderSelectionPolicy&) = delete;
>      virtual ~ProviderSelectionPolicy() = default;
>  
> -    virtual ProviderSelection determine_provider_selection_from_set_for_criteria(const Criteria& criteria, const std::set<Provider::Ptr>& providers) = 0;
> +    virtual ProviderSelection determine_provider_selection_for_criteria(
> +            const Criteria& criteria,
> +            const ProviderEnumerator& enumerator) = 0;
> +
>  protected:
>      ProviderSelectionPolicy() = default;
> -private:
> -    ProviderSelectionPolicy(const ProviderSelectionPolicy&) = delete;
> -    ProviderSelectionPolicy& operator=(const ProviderSelectionPolicy&) = delete;
>  };
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/providers/geoclue/geoclue.h'
> --- include/location_service/com/ubuntu/location/providers/geoclue/geoclue.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/providers/geoclue/geoclue.h	2014-06-24 16:02:38 +0000
> @@ -18,10 +18,10 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GEOCLUE_GEOCLUE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GEOCLUE_GEOCLUE_H_
>  
> -#include "core/dbus/service.h"
> -#include "core/dbus/traits/service.h"
> -#include "core/dbus/types/struct.h"
> -#include "core/dbus/types/stl/tuple.h"
> +#include <core/dbus/service.h>
> +#include <core/dbus/traits/service.h>
> +#include <core/dbus/types/struct.h>
> +#include <core/dbus/types/stl/tuple.h>
>  
>  #include <string>
>  
> @@ -43,13 +43,13 @@
>  
>      friend std::ostream& operator<<(std::ostream& out, const Status& status)
>      {
> -        static std::map<Status, std::string> lut = 
> -		{
> -                    {Status::error, "error"},
> -                    {Status::unavailable, "unavailable"},
> -                    {Status::acquiring, "acquiring"},
> -                    {Status::available, "available"}
> -		};
> +        static std::map<Status, std::string> lut =
> +        {
> +            {Status::error, "error"},
> +            {Status::unavailable, "unavailable"},
> +            {Status::acquiring, "acquiring"},
> +            {Status::available, "available"}
> +        };
>  
>          return out << lut[status];
>      }
> @@ -59,7 +59,7 @@
>          inline static std::string name()
>          {
>              return "GetProviderInfo";
> -        } 
> +        }
>          typedef Geoclue Interface;
>          typedef std::tuple<std::string, std::string> ResultType;
>          inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> @@ -70,7 +70,7 @@
>          inline static std::string name()
>          {
>              return "GetStatus";
> -        } 
> +        }
>          typedef Geoclue Interface;
>          typedef int32_t ResultType;
>          inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> @@ -81,7 +81,7 @@
>          inline static std::string name()
>          {
>              return "AddReference";
> -        } 
> +        }
>          typedef Geoclue Interface;
>          typedef void ResultType;
>          inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> @@ -92,7 +92,7 @@
>          inline static std::string name()
>          {
>              return "RemoveReference";
> -        } 
> +        }
>          typedef Geoclue Interface;
>          typedef void ResultType;
>          inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> @@ -105,7 +105,7 @@
>              inline static std::string name()
>              {
>                  return "GetAddress";
> -            } 
> +            }
>              typedef Address Interface;
>              typedef std::tuple<int32_t, std::map<std::string, std::string>, dbus::types::Struct<std::tuple<int32_t, double, double>>> ResultType;
>              inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> @@ -127,24 +127,24 @@
>  
>      struct Position
>      {
> -    	struct Field
> -    	{
> +        struct Field
> +        {
>              Field() = delete;
>  
>              static const int none = 0;
>              static const int latitude = 1;
>              static const int longitude = 2;
>              static const int altitude = 3;
> -    	};
> +        };
>  
> -    	typedef std::bitset<4> FieldFlags;
> +        typedef std::bitset<4> FieldFlags;
>  
>          struct GetPosition
>          {
>              inline static std::string name()
>              {
>                  return "GetPosition";
> -            } 
> +            }
>              typedef Position Interface;
>              typedef std::tuple<int32_t, int32_t, double, double, double, dbus::types::Struct<std::tuple<int32_t, double, double>>> ResultType;
>              inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> @@ -166,24 +166,24 @@
>  
>      struct Velocity
>      {
> -    	struct Field
> -    	{
> +        struct Field
> +        {
>              Field() = delete;
>  
>              static const int none = 0;
>              static const int speed = 1;
>              static const int direction = 2;
>              static const int climb = 3;
> -    	};
> +        };
>  
> -    	typedef std::bitset<4> FieldFlags;
> +        typedef std::bitset<4> FieldFlags;
>  
>          struct GetVelocity
>          {
>              inline static std::string name()
>              {
>                  return "GetVelocity";
> -            } 
> +            }
>              typedef Velocity Interface;
>              typedef std::tuple<int32_t, int32_t, double, double, double> ResultType;
>              inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> 
> === modified file 'include/location_service/com/ubuntu/location/providers/geoclue/provider.h'
> --- include/location_service/com/ubuntu/location/providers/geoclue/provider.h	2013-05-29 06:04:02 +0000
> +++ include/location_service/com/ubuntu/location/providers/geoclue/provider.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GEOCLUE_PROVIDER_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GEOCLUE_PROVIDER_H_
>  
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/provider_factory.h"
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/provider_factory.h>
>  
>  namespace com
>  {
> @@ -36,9 +36,6 @@
>    public:
>      static Provider::Ptr create_instance(const ProviderFactory::Configuration&);
>  
> -    static const Provider::FeatureFlags& default_feature_flags();
> -    static const Provider::RequirementFlags& default_requirement_flags();
> -
>      struct Configuration
>      {
>          static std::string key_name() { return "name"; }
> @@ -46,8 +43,8 @@
>          std::string name;
>          std::string path;
>  
> -        Provider::FeatureFlags features;
> -        Provider::RequirementFlags requirements;
> +        Provider::Features features = Provider::Features::none;
> +        Provider::Requirements requirements = Provider::Requirements::none;
>      };
>  
>      Provider(const Configuration& config);
> 
> === removed directory 'include/location_service/com/ubuntu/location/providers/gps'
> === modified file 'include/location_service/com/ubuntu/location/providers/skyhook/provider.h'
> --- include/location_service/com/ubuntu/location/providers/skyhook/provider.h	2013-05-29 06:04:02 +0000
> +++ include/location_service/com/ubuntu/location/providers/skyhook/provider.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_SKYHOOK_PROVIDER_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_SKYHOOK_PROVIDER_H_
>  
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/provider_factory.h"
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/provider_factory.h>
>  
>  #include <memory>
>  
> 
> === modified file 'include/location_service/com/ubuntu/location/proxy_provider.h'
> --- include/location_service/com/ubuntu/location/proxy_provider.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/proxy_provider.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROXY_PROVIDER_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROXY_PROVIDER_H_
>  
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/provider_selection_policy.h"
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/provider_selection_policy.h>
>  
>  #include <bitset>
>  #include <memory>
> @@ -38,10 +38,6 @@
>      ProxyProvider(const ProviderSelection& selection);
>      ~ProxyProvider() noexcept;
>  
> -    ChannelConnection subscribe_to_position_updates(std::function<void(const Update<Position>&)> f);
> -    ChannelConnection subscribe_to_heading_updates(std::function<void(const Update<Heading>&)> f);
> -    ChannelConnection subscribe_to_velocity_updates(std::function<void(const Update<Velocity>&)> f);
> -
>      virtual void start_position_updates();
>      virtual void stop_position_updates();
>  
> @@ -52,9 +48,14 @@
>      virtual void stop_heading_updates();
>      
>  private:
> -    Provider::Ptr position_updates_provider;
> -    Provider::Ptr heading_updates_provider;
> -    Provider::Ptr velocity_updates_provider;
> +    ProviderSelection providers;
> +
> +    struct
> +    {
> +        core::ScopedConnection position_updates;
> +        core::ScopedConnection heading_updates;
> +        core::ScopedConnection velocity_updates;
> +    } connections;
>  };
>  }
>  }
> 
> === added file 'include/location_service/com/ubuntu/location/satellite_based_positioning_state.h'
> --- include/location_service/com/ubuntu/location/satellite_based_positioning_state.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/satellite_based_positioning_state.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,40 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *

Update the copyright to 2014.

> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SATELLITE_BASED_POSITIONING_STATE_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SATELLITE_BASED_POSITIONING_STATE_H_
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +/**
> + * @brief The SatelliteBasedPositioningState enum describes whether satellite
> + * assisted positioning is enabled or disabled.
> + */
> +enum class SatelliteBasedPositioningState
> +{
> +    on, ///< Satellite assisted positioning is on.
> +    off ///< Satellite assisted positioning is off.
> +};
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SATELLITE_BASED_POSITIONING_STATE_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/service/configuration.h'
> --- include/location_service/com/ubuntu/location/service/configuration.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/service/configuration.h	2014-06-24 16:02:38 +0000
> @@ -18,11 +18,11 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_CONFIGURATION_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_CONFIGURATION_H_
>  
> -#include "com/ubuntu/location/service/permission_manager.h"
> +#include <com/ubuntu/location/service/permission_manager.h>
>  
> -#include "com/ubuntu/location/engine.h"
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/provider_selection_policy.h"
> +#include <com/ubuntu/location/engine.h>
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/provider_selection_policy.h>
>  
>  #include <set>
>  
> 
> === modified file 'include/location_service/com/ubuntu/location/service/default_configuration.h'
> --- include/location_service/com/ubuntu/location/service/default_configuration.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/service/default_configuration.h	2014-06-24 16:02:38 +0000
> @@ -18,7 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DEFAULT_CONFIGURATION_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DEFAULT_CONFIGURATION_H_
>  
> -#include "com/ubuntu/location/service/configuration.h"
> +#include <com/ubuntu/location/service/configuration.h>
>  
>  #include <set>
>  
> 
> === modified file 'include/location_service/com/ubuntu/location/service/default_permission_manager.h'
> --- include/location_service/com/ubuntu/location/service/default_permission_manager.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/service/default_permission_manager.h	2014-06-24 16:02:38 +0000
> @@ -18,7 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DEFAULT_PERMISSION_MANAGER_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DEFAULT_PERMISSION_MANAGER_H_
>  
> -#include "com/ubuntu/location/service/permission_manager.h"
> +#include <com/ubuntu/location/service/permission_manager.h>
>  
>  #include <sys/types.h>
>  #include <unistd.h>
> 
> === modified file 'include/location_service/com/ubuntu/location/service/interface.h'
> --- include/location_service/com/ubuntu/location/service/interface.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/service/interface.h	2014-06-24 16:02:38 +0000
> @@ -18,7 +18,9 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_INTERFACE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_INTERFACE_H_
>  
> -#include "com/ubuntu/location/service/session/interface.h"
> +#include <com/ubuntu/location/service/session/interface.h>
> +
> +#include <com/ubuntu/location/space_vehicle.h>
>  
>  #include <core/dbus/service.h>
>  #include <core/dbus/traits/service.h>
> @@ -35,18 +37,31 @@
>  {
>  namespace location
>  {
> -
>  struct Criteria;
> -
>  namespace service
>  {
> +/**
> + * @brief The Interface class models the primary interface to the location service.
> + */
>  class Interface
>  {
>    protected:
>      struct Errors
>      {
> -        struct InsufficientPermissions { inline static std::string name() { return "com.ubuntu.location.Service.Error.InsufficientPermissions"; } };
> -        struct CreatingSession { inline static std::string name() { return "com.ubuntu.location.Service.Error.CreatingSession"; } };
> +        struct InsufficientPermissions
> +        {
> +            inline static std::string name()
> +            {
> +                return "com.ubuntu.location.Service.Error.InsufficientPermissions";
> +            }
> +        };
> +        struct CreatingSession
> +        {
> +            inline static std::string name()
> +            {
> +                return "com.ubuntu.location.Service.Error.CreatingSession";
> +            }
> +        };
>      };
>  
>      struct CreateSessionForCriteria
> @@ -64,7 +79,82 @@
>  
>          typedef dbus::types::ObjectPath ResultType;
>  
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> +        inline static const std::chrono::milliseconds default_timeout()
> +        {
> +            return std::chrono::seconds{1};
> +        }
> +    };
> +
> +    struct Properties
> +    {
> +        struct DoesSatelliteBasedPositioning
> +        {
> +            inline static const std::string& name()
> +            {
> +                static const std::string s
> +                {
> +                    "DoesSatelliteBasedPositioning"
> +                };
> +                return s;
> +            }
> +
> +            typedef com::ubuntu::location::service::Interface Interface;
> +            typedef bool ValueType;
> +            static const bool readable = true;
> +            static const bool writable = true;
> +        };
> +
> +        struct DoesReportCellAndWifiIds
> +        {
> +            inline static const std::string& name()
> +            {
> +                static const std::string s
> +                {
> +                    "DoesReportCellAndWifiIds"
> +                };
> +                return s;
> +            }
> +
> +            typedef com::ubuntu::location::service::Interface Interface;
> +            typedef bool ValueType;
> +            static const bool readable = true;
> +            static const bool writable = true;
> +        };
> +
> +        struct IsOnline
> +        {
> +            inline static const std::string& name()
> +            {
> +                static const std::string s
> +                {
> +                    "IsOnline"
> +                };
> +                return s;
> +            }
> +
> +            typedef com::ubuntu::location::service::Interface Interface;
> +            typedef bool ValueType;
> +            static const bool readable = true;
> +            static const bool writable = true;
> +        };
> +
> +        struct VisibleSpaceVehicles
> +        {
> +            inline static const std::string& name()
> +            {
> +                static const std::string s
> +                {
> +                    "VisibleSpaceVehicles"
> +                };
> +                return s;
> +            }
> +
> +            typedef com::ubuntu::location::service::Interface Interface;
> +            typedef std::map<com::ubuntu::location::SpaceVehicle::Key, com::ubuntu::location::SpaceVehicle> ValueType;
> +
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
>      };
>  
>      Interface() = default;
> @@ -72,6 +162,9 @@
>    public:
>      typedef std::shared_ptr<Interface> Ptr;
>  
> +    /**
> +     * @brief Queries the path that this object is known under.
> +     */
>      inline static const std::string& path()
>      {
>          static const std::string s{"/com/ubuntu/location/Service"};
> @@ -82,6 +175,40 @@
>      Interface& operator=(const Interface&) = delete;
>      virtual ~Interface() = default;
>  
> +    /**
> +     * @brief Whether the service uses satellite-based positioning.
> +     * @return  A setable/getable/observable property.
> +     */
> +    virtual core::Property<bool>& does_satellite_based_positioning() = 0;
> +
> +    /**
> +     * @brief Whether the overall service and its positioning engine is online or not.
> +     * @return  A setable/getable/observable property.
> +     */
> +    virtual core::Property<bool>& is_online() = 0;
> +
> +    /**
> +     * @brief Whether the engine and its providers/reporters do call home to
> +     * report reference locations together with wifi and cell ids.
> +     *
> +     * We consider this feature privacy sensitive and it defaults to false. The
> +     * user has to explicitly opt-in into this feature.
> +     *
> +     * @return A setable/getable/observable property.
> +     */
> +    virtual core::Property<bool>& does_report_cell_and_wifi_ids() = 0;
> +
> +    /**
> +      * @brief All space vehicles currently visible.
> +      */
> +    virtual core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles() = 0;
> +
> +    /**
> +     * @brief Starts a new session for the given criteria
> +     * @throw std::runtime_error in case of errors.
> +     * @param criteria The client's requirements in terms of accuraccy and functionality
> +     * @return A session instance.
> +     */
>      virtual session::Interface::Ptr create_session_for_criteria(const Criteria& criteria) = 0;
>  };
>  }
> @@ -111,6 +238,6 @@
>  }
>  }
>  
> -#include "com/ubuntu/location/codec.h"
> +#include <com/ubuntu/location/codec.h>
>  
>  #endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_INTERFACE_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/service/permission_manager.h'
> --- include/location_service/com/ubuntu/location/service/permission_manager.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/service/permission_manager.h	2014-06-24 16:02:38 +0000
> @@ -18,10 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_PERMISSION_MANAGER_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_PERMISSION_MANAGER_H_
>  
> -#include "com/ubuntu/location/channel.h"
> -#include "com/ubuntu/location/provider_selection_policy.h"
> -
> -#include <functional>
> +#include <memory>
>  
>  namespace com
>  {
> @@ -29,29 +26,47 @@
>  {
>  namespace location
>  {
> +struct Criteria;
>  namespace service
>  {
> +/** @brief Credentials of a remote session. */
>  struct Credentials
>  {
> +    /** @brief The process id of the remote peer. */
>      pid_t pid;
> +    /** @brief The user id the remote peer runs under. */
>      uid_t uid;
>  };
>  
> +/**
> + * @brief The PermissionManager class is an interface to check whether an application
> + * is allowed to access the location services.
> + */
>  class PermissionManager
>  {
>  public:
> +    /** Manager pointer type. */
>      typedef std::shared_ptr<PermissionManager> Ptr;
>  
> +    /**
> +     * @brief The Result enum summarizes the results of a query for permissions.
> +     */
>      enum class Result
>      {
> -        granted,
> -        rejected
> +        granted, ///< The app is allowed to access the location service.
> +        rejected ///< The app is not allowed to access the location service.
>      };
>  
>      virtual ~PermissionManager() = default;
>      PermissionManager(const PermissionManager&) = delete;
>      PermissionManager& operator=(const PermissionManager&) = delete;
>  
> +    /**
> +     * @brief Checks whether the app with the given credentials is allowed to access the service for the given criteria.
> +     * @param criteria The requirements of the remote peer.
> +     * @param credentials The credentials identifying the remote peer.
> +     * @return Result::granted if the remote peer is allowed to access the location service, Result::rejected otherwise.
> +     */
>      virtual Result check_permission_for_credentials(
>          const Criteria& criteria,
>          const Credentials& credentials) = 0;
> 
> === modified file 'include/location_service/com/ubuntu/location/service/session/implementation.h'
> --- include/location_service/com/ubuntu/location/service/session/implementation.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/service/session/implementation.h	2014-06-24 16:02:38 +0000
> @@ -18,9 +18,9 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_IMPLEMENTATION_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_IMPLEMENTATION_H_
>  
> -#include "com/ubuntu/location/service/session/skeleton.h"
> +#include <com/ubuntu/location/service/session/skeleton.h>
>  
> -#include "com/ubuntu/location/provider.h"
> +#include <com/ubuntu/location/provider.h>
>  
>  #include <memory>
>  
> @@ -34,13 +34,10 @@
>  {
>  namespace session
>  {
> -class Implementation : public Skeleton
> +class Implementation : public Interface
>  {
>    public:
> -    Implementation(
> -        const core::dbus::Bus::Ptr& bus,
> -        const core::dbus::types::ObjectPath& session_path,
> -        const Provider::Ptr& provider);
> +    Implementation(const Provider::Ptr& provider);
>      Implementation(const Implementation&) = delete;
>      virtual ~Implementation() noexcept;
>      Implementation& operator=(const Implementation&) = delete;
> 
> === modified file 'include/location_service/com/ubuntu/location/service/session/interface.h'
> --- include/location_service/com/ubuntu/location/service/session/interface.h	2014-03-05 12:57:39 +0000
> +++ include/location_service/com/ubuntu/location/service/session/interface.h	2014-06-24 16:02:38 +0000
> @@ -18,16 +18,13 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_INTERFACE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_INTERFACE_H_
>  
> -#include "com/ubuntu/location/channel.h"
> -#include "com/ubuntu/location/heading.h"
> -#include "com/ubuntu/location/position.h"
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/update.h"
> -#include "com/ubuntu/location/velocity.h"
> +#include <com/ubuntu/location/heading.h>
> +#include <com/ubuntu/location/position.h>
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/update.h>
> +#include <com/ubuntu/location/velocity.h>
>  
> -#include <core/dbus/codec.h>
> -#include <core/dbus/traits/service.h>
> -#include <core/dbus/types/object_path.h>
> +#include <core/property.h>
>  
>  namespace com
>  {
> @@ -39,176 +36,70 @@
>  {
>  namespace session
>  {
> +/**
> + * @brief Models a session with the location service.
> + */
>  class Interface
>  {
>  public:
> -    struct UpdatePosition
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "UpdatePosition"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::milliseconds{250}; }
> -    };
> -
> -    struct UpdateVelocity
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "UpdateVelocity"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::milliseconds{250}; }
> -    };
> -
> -    struct UpdateHeading
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "UpdateHeading"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::milliseconds{250}; }
> -    };
> -
> -    struct StartPositionUpdates
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "StartPositionUpdates"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> -    };
> -
> -    struct StopPositionUpdates
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "StopPositionUpdates"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> -    };
> -
> -    struct StartVelocityUpdates
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "StartVelocityUpdates"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> -    };
> -
> -    struct StopVelocityUpdates
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "StopVelocityUpdates"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> -    };
> -
> -    struct StartHeadingUpdates
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "StartHeadingUpdates"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> -    };
> -
> -    struct StopHeadingUpdates
> -    {
> -        typedef com::ubuntu::location::service::session::Interface Interface;
> -
> -        inline static const std::string& name()
> -        {
> -            static const std::string s
> -            {
> -                "StopHeadingUpdates"
> -            };
> -            return s;
> -        }
> -
> -        typedef void ResultType;
> -
> -        inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> -    };
> +    struct UpdatePosition;
> +    struct UpdateVelocity;
> +    struct UpdateHeading;
> +
> +    struct StartPositionUpdates;
> +    struct StopPositionUpdates;
> +
> +    struct StartVelocityUpdates;
> +    struct StopVelocityUpdates;
> +
> +    struct StartHeadingUpdates;
> +    struct StopHeadingUpdates;
>  
>      struct Errors
>      {
> -        struct ErrorParsingUpdate { inline static std::string name() { return "com.ubuntu.location.Service.Session.ErrorParsingUpdate"; } };
> -        struct ErrorStartingUpdate { inline static std::string name() { return "com.ubuntu.location.Service.Session.ErrorStartingUpdate"; } };
> -        struct ErrorStoppingUpdate { inline static std::string name() { return "com.ubuntu.location.Service.Session.ErrorStoppingUpdate"; } };
> +        struct ErrorParsingUpdate;
> +        struct ErrorStartingUpdate;
> +    };
> +    /**
> +     * @brief Encapsulates updates provided for this session, and the ability to enable/disable updates.
> +     */
> +    struct Updates
> +    {
> +        /**
> +         * @brief The Status enum models the possible states of updates.
> +         */
> +        enum class Status
> +        {
> +            enabled, ///< Updates are enabled and delivered to this session.
> +            disabled ///< Updates are disabled and not delivered to this session.
> +        };
> +
> +        /**
> +         * @brief Updates for position measurements.
> +         */
> +        core::Property<Update<Position>> position{};
> +        /**
> +         * @brief Status of position updates, mutable.
> +         */
> +        core::Property<Status> position_status{Status::disabled};
> +
> +        /**
> +         * @brief Updates for the heading measurements.
> +         */
> +        core::Property<Update<Heading>> heading{};
> +        /**
> +         * @brief Status of position updates, mutable.
> +         */
> +        core::Property<Status> heading_status{Status::disabled};
> +
> +        /**
> +         * @brief Updates for velocity measurements.
> +         */
> +        core::Property<Update<Velocity>> velocity{};
> +        /**
> +         * @brief Status of velocity updates, mutable.
> +         */
> +        core::Property<Status> velocity_status{Status::disabled};
>      };
>  
>      typedef std::shared_ptr<Interface> Ptr;
> @@ -217,58 +108,23 @@
>      virtual ~Interface() noexcept;
>      Interface& operator=(const Interface&) = delete;
>  
> -    virtual const core::dbus::types::ObjectPath& path() const = 0;
> -
> -    ChannelConnection install_position_updates_handler(std::function<void(const Update<Position>&)> handler);
> -    ChannelConnection install_velocity_updates_handler(std::function<void(const Update<Velocity>&)> handler);
> -    ChannelConnection install_heading_updates_handler(std::function<void(const Update<Heading>&)> handler);
> -
> -    virtual void start_position_updates() = 0;
> -    virtual void stop_position_updates() noexcept = 0;
> -    virtual void start_velocity_updates() = 0;
> -    virtual void stop_velocity_updates() noexcept = 0;
> -    virtual void start_heading_updates() = 0;
> -    virtual void stop_heading_updates() noexcept = 0;
> -
> -protected:
> +    /**
> +     * @brief Provides access to the updates delivered for this session.
> +     * @return A mutable reference to updates.
> +     */
> +    virtual Updates& updates();
> +
> +protected:    
>      Interface();
>  
> -    Channel<Update<Position>>& access_position_updates_channel();
> -    Channel<Update<Heading>>& access_heading_updates_channel();
> -    Channel<Update<Velocity>>& access_velocity_updates_channel();
> -
>  private:
>      struct Private;
> -    std::unique_ptr<Private> d;
> -};
> -}
> -}
> -}
> -}
> -}
> -namespace core
> -{
> -namespace dbus
> -{
> -namespace traits
> -{
> -template<>
> -struct Service<com::ubuntu::location::service::session::Interface>
> -{
> -    static const std::string& interface_name()
> -    {
> -        static const std::string s
> -        {
> -            "com.ubuntu.location.Service.Session"
> -        };
> -        return s;
> -    }
> -};
> -}
> -}
> -}
> -
> -
> -#include "com/ubuntu/location/codec.h"
> +    std::shared_ptr<Private> d;
> +};
> +}
> +}
> +}
> +}
> +}
>  
>  #endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_INTERFACE_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/service/session/skeleton.h'
> --- include/location_service/com/ubuntu/location/service/session/skeleton.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/service/session/skeleton.h	2014-06-24 16:02:38 +0000
> @@ -18,19 +18,19 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_SKELETON_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_SKELETON_H_
>  
> -#include "com/ubuntu/location/service/session/interface.h"
> +#include <com/ubuntu/location/service/session/interface.h>
>  
> -#include "com/ubuntu/location/channel.h"
> -#include "com/ubuntu/location/heading.h"
> -#include "com/ubuntu/location/position.h"
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/update.h"
> -#include "com/ubuntu/location/velocity.h"
> +#include <com/ubuntu/location/heading.h>
> +#include <com/ubuntu/location/position.h>
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/update.h>
> +#include <com/ubuntu/location/velocity.h>
>  
>  #include <core/dbus/message.h>
> +#include <core/dbus/object.h>
>  #include <core/dbus/skeleton.h>
>  
> -#include <functional>
> +#include <memory>
>  
>  namespace com
>  {
> @@ -44,19 +44,74 @@
>  {
>  class Skeleton : public core::dbus::Skeleton<Interface>
>  {
> -  public:
> -    Skeleton(
> -        const core::dbus::Bus::Ptr& bus,
> -        const core::dbus::types::ObjectPath& session_path);
> -    Skeleton(const Skeleton&) = delete;
> +public:
> +    // All local, i.e., in-process creation-time properties of the Skeleton.
> +    struct Local
> +    {
> +        // The actual implementation of com::ubuntu::location::service::session::Interface.
> +        Interface::Ptr impl;
> +        // The bus connection that the object is exposed upon.
> +        core::dbus::Bus::Ptr bus;
> +    };
> +
> +    // We communicate position, heading and velocity updates to the client
> +    // via an explicit function call. The reason is simple: We want to know
> +    // whether the client is still alive and responding as expected to make sure
> +    // that we stop positioning as early as possible.
> +    struct Remote
> +    {
> +        // The remote object corresponding to the client, implementing
> +        // com.ubuntu.location.service.session.Interface
> +        core::dbus::Object::Ptr object;
> +    };
> +
> +    struct Configuration
> +    {
> +        // The object path of the session object, shared between clients and service.
> +        core::dbus::types::ObjectPath path;
> +        // Local attributes
> +        Local local;
> +        // Remote attributes
> +        Remote remote;
> +    };
> +
> +    Skeleton(const Configuration& configuration);
>      virtual ~Skeleton() noexcept;
> -    Skeleton& operator=(const Skeleton&) = delete;
>  
>      virtual const core::dbus::types::ObjectPath& path() const;
>  
> -  private:
> -    struct Private;
> -    std::unique_ptr<Private> d;
> +private:
> +    // Handle incoming requests for Start/StopPositionUpdates
> +    virtual void on_start_position_updates(const core::dbus::Message::Ptr&);
> +    virtual void on_stop_position_updates(const core::dbus::Message::Ptr&);
> +    // Handles incoming requests for Start/StopHeadingUpdates
> +    virtual void on_start_heading_updates(const core::dbus::Message::Ptr&);
> +    virtual void on_stop_heading_updates(const core::dbus::Message::Ptr&);
> +    // Handles incoming requests for Start/StopVelocityUpdates
> +    virtual void on_start_velocity_updates(const core::dbus::Message::Ptr&);
> +    virtual void on_stop_velocity_updates(const core::dbus::Message::Ptr&);
> +
> +    // Invoked whenever the actual session impl. for the session reports a position update.
> +    virtual void on_position_changed(const Update<Position>& position);
> +    // Invoked whenever the actual session impl. reports a heading update.
> +    virtual void on_heading_changed(const Update<Heading>& heading);
> +    // Invoked whenever the actual session impl. reports a velocity update.
> +    virtual void on_velocity_changed(const Update<Velocity>& velocity);
> +
> +    // Stores all attributes passed at creation time.
> +    Configuration configuration;
> +    // The DBus object corresponding to the session.
> +    core::dbus::Object::Ptr object;
> +    // Scoped connections for automatically disconnecting on destruction
> +    struct
> +    {
> +        // Corresponds to position updates coming in from the actual implementation instance.
> +        core::ScopedConnection position_changed;
> +        // Corresponds to heading updates coming in from the actual implementation instance.
> +        core::ScopedConnection heading_changed;
> +        // Corresponds to velocity updates coming in from the actual implementation instance.
> +        core::ScopedConnection velocity_changed;
> +    } connections;
>  };
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/service/session/stub.h'
> --- include/location_service/com/ubuntu/location/service/session/stub.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/service/session/stub.h	2014-06-24 16:02:38 +0000
> @@ -18,14 +18,13 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_STUB_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SESSION_SESSION_STUB_H_
>  
> -#include "com/ubuntu/location/service/session/interface.h"
> +#include <com/ubuntu/location/service/session/interface.h>
>  
> -#include "com/ubuntu/location/channel.h"
> -#include "com/ubuntu/location/heading.h"
> -#include "com/ubuntu/location/position.h"
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/update.h"
> -#include "com/ubuntu/location/velocity.h"
> +#include <com/ubuntu/location/heading.h>
> +#include <com/ubuntu/location/position.h>
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/update.h>
> +#include <com/ubuntu/location/velocity.h>
>  
>  #include <core/dbus/stub.h>
>  
> 
> === modified file 'include/location_service/com/ubuntu/location/service/skeleton.h'
> --- include/location_service/com/ubuntu/location/service/skeleton.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/service/skeleton.h	2014-06-24 16:02:38 +0000
> @@ -18,10 +18,13 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SKELETON_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SKELETON_H_
>  
> -#include "com/ubuntu/location/service/interface.h"
> -#include "com/ubuntu/location/service/permission_manager.h"
> -#include "com/ubuntu/location/service/session/interface.h"
> +#include <com/ubuntu/location/service/interface.h>
> +#include <com/ubuntu/location/service/permission_manager.h>
> +#include <com/ubuntu/location/service/session/interface.h>
>  
> +#include <core/dbus/dbus.h>
> +#include <core/dbus/object.h>
> +#include <core/dbus/property.h>
>  #include <core/dbus/skeleton.h>
>  
>  namespace com
> @@ -32,20 +35,111 @@
>  {
>  namespace service
>  {
> -class Skeleton : public core::dbus::Skeleton<com::ubuntu::location::service::Interface>,
> -                 public std::enable_shared_from_this<Skeleton>
> +class Skeleton
> +        : public core::dbus::Skeleton<com::ubuntu::location::service::Interface>,
> +          public std::enable_shared_from_this<Skeleton>
>  {
> -  public:
> +public:
>      typedef std::shared_ptr<Skeleton> Ptr;
> -    
> -    Skeleton(const dbus::Bus::Ptr& connection, const PermissionManager::Ptr& permission_manager);
> -    Skeleton(const Skeleton&) = delete;
> -    Skeleton& operator=(const Skeleton&) = delete;
> +
> +    // Models resolution of an incoming dbus message to the credentials of the message sender.
> +    struct CredentialsResolver
> +    {
> +        typedef std::shared_ptr<CredentialsResolver> Ptr;
> +
> +        CredentialsResolver() = default;
> +        virtual ~CredentialsResolver() = default;
> +
> +        // Resolves the sender of msg to the respective credentials.
> +        virtual Credentials resolve_credentials_for_incoming_message(const core::dbus::Message::Ptr& msg) = 0;
> +    };
> +
> +    // Implements CredentialsResolver by reaching out to the dbus daemon and
> +    // invoking:
> +    //   * GetConnectionUnixProcessID
> +    //   * GetConnectionUnixUser
> +    struct DBusDaemonCredentialsResolver : public CredentialsResolver
> +    {
> +        // Sets up a new instance for the given bus connection.
> +        DBusDaemonCredentialsResolver(const core::dbus::Bus::Ptr& bus);
> +
> +        // Resolves the sender of msg to pid, uid by calling out to the dbus daemon.
> +        Credentials resolve_credentials_for_incoming_message(const core::dbus::Message::Ptr& msg);
> +
> +        // Stub for accessing the dbus daemon.
> +        core::dbus::DBus daemon;
> +    };
> +
> +    // Models the generation of stable and unique object paths for client-specific sessions.
> +    // The requirements for the resulting object path are:
> +    //   * Unique for the entire system over its complete lifetime
> +    //   * Stable with respect to an app. That is, one app is always assigned the same object path.
> +    struct ObjectPathGenerator
> +    {
> +        typedef std::shared_ptr<ObjectPathGenerator> Ptr;
> +
> +        ObjectPathGenerator() = default;
> +        virtual ~ObjectPathGenerator() = default;
> +
> +        // Calculates an object path from pid and uid. The default implementation
> +        // creates the path according to the following steps:
> +        //    [1.] Query the AppArmor profile name for pid in credentials.
> +        //    [1.1] If the process is running unconfined, rely on a counter to assemble the session name.
> +        //    [1.2] If the process is confined, use the AppArmor profile name to generate the path.
> +        virtual core::dbus::types::ObjectPath object_path_for_caller_credentials(const Credentials& credentials);
> +    };
> +
> +    struct Configuration
> +    {
> +        // DBus connection set up for handling requests to the service.
> +        core::dbus::Bus::Ptr incoming;
> +        // DBus connection for reaching out to other services in a non-blocking way.
> +        core::dbus::Bus::Ptr outgoing;
> +        // An implementation of CredentialsResolver for resolving incoming message sender
> +        // to Credentials = uid, pid.
> +        CredentialsResolver::Ptr credentials_resolver;
> +        // An implementation of ObjectPathGenerator for generating session names.
> +        ObjectPathGenerator::Ptr object_path_generator;
> +        // Permission manager implementation for verifying incoming requests.
> +        PermissionManager::Ptr permission_manager;
> +    };
> +
> +    Skeleton(const Configuration& configuration);
>      ~Skeleton() noexcept;
>  
> -  private:
> -    struct Private;
> -    std::shared_ptr<Private> d;
> +    // From com::ubuntu::location::service::Interface
> +    core::Property<bool>& does_satellite_based_positioning();
> +    core::Property<bool>& does_report_cell_and_wifi_ids();
> +    core::Property<bool>& is_online();
> +    core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles();
> +
> +private:
> +    // Handles incoming message calls for create_session_for_criteria.
> +    // Dispatches to the actual implementation, and manages object lifetimes.
> +    void handle_create_session_for_criteria(const core::dbus::Message::Ptr& msg);
> +
> +    // Tries to register the given session under the given path in the session store.
> +    // Returns true iff the session has been added to the store.
> +    bool add_to_session_store_for_path(
> +            const core::dbus::types::ObjectPath& path,
> +            const session::Interface::Ptr& session);
> +
> +    // Stores the configuration passed in at creation time.
> +    Configuration configuration;
> +    // The skeleton object representing com.ubuntu.location.service.Interface on the bus.
> +    core::dbus::Object::Ptr object;
> +    // DBus properties as exposed on the bus for com.ubuntu.location.service.Interface
> +    struct
> +    {
> +        std::shared_ptr< core::dbus::Property<Interface::Properties::DoesSatelliteBasedPositioning> > does_satellite_based_positioning;
> +        std::shared_ptr< core::dbus::Property<Interface::Properties::DoesReportCellAndWifiIds> > does_report_cell_and_wifi_ids;
> +        std::shared_ptr< core::dbus::Property<Interface::Properties::IsOnline> > is_online;
> +        std::shared_ptr< dbus::Property<Interface::Properties::VisibleSpaceVehicles> > visible_space_vehicles;
> +    } properties;
> +    // Guards the session store.
> +    std::mutex guard;
> +    // Keeps track of running sessions, keying them by their unique object path.
> +    std::map<dbus::types::ObjectPath, std::shared_ptr<session::Interface>> session_store;
>  };
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/service/stub.h'
> --- include/location_service/com/ubuntu/location/service/stub.h	2014-01-31 11:08:33 +0000
> +++ include/location_service/com/ubuntu/location/service/stub.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_STUB_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_STUB_H_
>  
> -#include "com/ubuntu/location/service/interface.h"
> -#include "com/ubuntu/location/service/session/interface.h"
> +#include <com/ubuntu/location/service/interface.h>
> +#include <com/ubuntu/location/service/session/interface.h>
>  
>  #include <core/dbus/stub.h>
>  
> @@ -40,6 +40,10 @@
>      ~Stub() noexcept;
>  
>      session::Interface::Ptr create_session_for_criteria(const Criteria& criteria);
> +    core::Property<bool>& does_satellite_based_positioning();
> +    core::Property<bool>& does_report_cell_and_wifi_ids();
> +    core::Property<bool>& is_online();    
> +    core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles();
>  
>    private:
>      struct Private;
> 
> === added file 'include/location_service/com/ubuntu/location/space_vehicle.h'
> --- include/location_service/com/ubuntu/location/space_vehicle.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/space_vehicle.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,123 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *

Update the copyright to 2014.

> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SPACE_VEHICLE_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SPACE_VEHICLE_H_
> +
> +#include <com/ubuntu/location/units/units.h>
> +
> +#include <iostream>
> +#include <map>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +/** @brief A space-vehicle as visible to providers. */
> +struct SpaceVehicle
> +{
> +    /** @brief Numeric Id of an individual SpaceVehicle. */
> +    typedef std::uint32_t Id;
> +
> +    /** @brief Enumerates all known space-vehicle types. */
> +    enum class Type
> +    {
> +        unknown, ///< Unknown (and thus invalid) type.
> +        beidou, ///< People's Republic of China's regional system, currently limited to Asia and the West Pacific
> +        galileo, ///< A global system being developed by the European Union and other partner countries, planned to be operational by 2014 (and fully deployed by 2019).
> +        glonass, ///< Russia's global navigation system. Fully operational worldwide.
> +        gps, ///< Fully operational worldwide.
> +        compass, ///< People's Republic of China's global system, planned to be operational by 2020.
> +        irnss, ///< India's regional navigation system, planned to be operational by 2014, covering India and Northern Indian Ocean.
> +        qzss ///< Japanese regional system covering Asia and Oceania.
> +    };    
> +
> +    /** @brief Uniquely identifies a space vehicle, given its type and its id. */
> +    struct Key
> +    {
> +        Type type = Type::unknown; ///< The positioning system this vehicle belongs to.
> +        Id id = 0; ///< Unique id of the space vehicle.
> +
> +        inline bool operator==(const SpaceVehicle::Key& rhs) const
> +        {
> +            return type == rhs.type && id == rhs.id;
> +        }
> +
> +        inline bool operator<(const SpaceVehicle::Key& rhs) const
> +        {
> +            if (type != rhs.type)
> +                return type < rhs.type;
> +
> +            return id < rhs.id;
> +        }
> +    };
> +
> +    inline bool operator==(const SpaceVehicle& rhs) const
> +    {
> +        return key == rhs.key &&

IS it possible that we have the same key and other data is diff. The key is uniuqe and idenifies an instance. Is that instance a software object instance of a SV instance?

> +                has_almanac_data == rhs.has_almanac_data &&
> +                has_ephimeris_data == rhs.has_ephimeris_data &&
> +                used_in_fix == rhs.used_in_fix &&
> +                units::roughly_equals(azimuth, rhs.azimuth) &&
> +                units::roughly_equals(elevation, rhs.elevation);
> +    }
> +
> +    inline bool operator<(const SpaceVehicle& rhs) const
> +    {
> +        return key < rhs.key;
> +    }
> +
> +    Key key; ///< Unique key identifying an instance.

AS I asked above is the a software object instance of a SV instance (I suspect in the second case).

> +    float snr = -std::numeric_limits<float>::max(); ///< Signal to noise ratio;
> +    bool has_almanac_data = false; ///< Almanac data available for this vehicle.
> +    bool has_ephimeris_data = false; ///< Ephimeris data is available for this vehicle.
> +    bool used_in_fix = false;  ///< This vehicle has been used to obtain a fix.
> +    units::Quantity<units::PlaneAngle> azimuth; ///< Azimuth of SV.
> +    units::Quantity<units::PlaneAngle> elevation; ///< Elevation of SV.
> +};
> +
> +inline std::ostream& operator<<(std::ostream& out, const SpaceVehicle& sv)
> +{
> +    static const std::map<SpaceVehicle::Type, std::string> lut =
> +    {
> +        {SpaceVehicle::Type::unknown, "unknown"},
> +        {SpaceVehicle::Type::beidou, "beidou"},
> +        {SpaceVehicle::Type::galileo, "galileo"},
> +        {SpaceVehicle::Type::glonass, "glonass"},
> +        {SpaceVehicle::Type::gps, "gps"},
> +        {SpaceVehicle::Type::compass, "compass"},
> +        {SpaceVehicle::Type::irnss, "irnss"},
> +        {SpaceVehicle::Type::qzss, "qzss" }

I like the use of maps for quick acess, but since we have an enumerator and a string, can't we just use a switch. Nevertheless this is not a huge concern.

> +    };
> +    return out << "("
> +               << "type: " << lut.at(sv.key.type) << ", "
> +               << "prn: " << sv.key.id << ", "
> +               << "snr: " << sv.snr << ", "
> +               << "has_almanac_data: " << sv.has_almanac_data << ", "
> +               << "has_ephimeris_data: " << sv.has_ephimeris_data << ", "
> +               << "used_in_fix: " << sv.used_in_fix << ", "
> +               << "azimuth: " << sv.azimuth << ", "
> +               << "elevation: " << sv.elevation
> +               << ")";
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SPACE_VEHICLE_H_
> 
> === modified file 'include/location_service/com/ubuntu/location/units/units.h'
> --- include/location_service/com/ubuntu/location/units/units.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/units/units.h	2014-06-24 16:02:38 +0000
> @@ -57,6 +57,12 @@
>  using boost::units::sin;
>  using boost::units::cos;
>  using boost::units::atan2;
> +
> +template<typename Unit>
> +inline bool roughly_equals(const Quantity<Unit>& lhs, const Quantity<Unit>& rhs)
> +{
> +    return std::fabs(lhs.value()-rhs.value()) <= std::numeric_limits<double>::epsilon();
> +}
>  }
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/update.h'
> --- include/location_service/com/ubuntu/location/update.h	2013-05-29 06:04:02 +0000
> +++ include/location_service/com/ubuntu/location/update.h	2014-06-24 16:02:38 +0000
> @@ -18,7 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_H_
>  
> -#include "com/ubuntu/location/clock.h"
> +#include <com/ubuntu/location/clock.h>
>  
>  #include <ostream>
>  
> @@ -28,27 +28,56 @@
>  {
>  namespace location
>  {
> +/**
> + * @brief Templated class that wraps a value and timestamp.
> + * @tparam T The contained value.
> + */
>  template<typename T>
>  struct Update
>  {
> -    Update(const T& value = T{}, const Clock::Timestamp& when = Clock::Timestamp{}) : value{value}, when{when}
> +    /**
> +      * @brief Constructs a valid update with the given value and timestamp.
> +      * @param [in] value The value delivered with this update.
> +      * @param [in] when The timestamp when the value was measured.
> +      */
> +    inline Update(const T& value = T{},
> +           const Clock::Timestamp& when = Clock::now())
> +        : value{value}, when{when}
>      {
>      }
>  
> -    bool operator==(const Update<T>& rhs) const
> +    /**
> +     * @brief operator == checks if two updates are equal.
> +     * @param [in] rhs The update to check against.
> +     * @return true iff this instance equals rhs.
> +     */
> +    inline bool operator==(const Update<T>& rhs) const
>      {
>          return value == rhs.value && when == rhs.when;
>      }
>  
> -    bool operator!=(const Update<T>& rhs) const
> +    /**
> +     * @brief operator != checks if two updates are unequal.
> +     * @param [in] rhs The update to check against.
> +     * @return true iff this instance does not equal rhs.
> +     */
> +    inline bool operator!=(const Update<T>& rhs) const
>      {
>          return !(value == rhs.value && when == rhs.when);
>      }
>  
> +    /** The value delivered with this update. */
>      T value;
> -    Clock::Timestamp when;
> +
> +    /** Time when the updated value was measured. */
> +    Clock::Timestamp when = Clock::beginning_of_time();
>  };
>  
> +/**
> + * @brief Pretty-prints the update to the provided output stream.
> + * @param out The stream to write to.
> + * @param update The value to be printed.
> + */
>  template<typename T>
>  inline std::ostream& operator<<(std::ostream& out, const Update<T>& update)
>  {
> 
> === modified file 'include/location_service/com/ubuntu/location/velocity.h'
> --- include/location_service/com/ubuntu/location/velocity.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/velocity.h	2014-06-24 16:02:38 +0000
> @@ -18,12 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_VELOCITY_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_VELOCITY_H_
>  
> -#include "com/ubuntu/location/accuracy.h"
> -#include "com/ubuntu/location/units/units.h"
> -
> -#include <limits>
> -#include <ostream>
> -#include <stdexcept>
> +#include <com/ubuntu/location/units/units.h>
>  
>  namespace com
>  {
> @@ -31,74 +26,8 @@
>  {
>  namespace location
>  {
> -struct Velocity
> -{
> -    typedef units::Velocity Unit;
> -    typedef units::Quantity<Unit> Quantity;
> -
> -    static inline const Quantity& min()
> -    {
> -        static const Quantity instance = Quantity::from_value(0.);
> -        return instance;
> -    }
> -
> -    static inline const Quantity max()
> -    {
> -        static const Quantity instance = Quantity::from_value(std::numeric_limits<double>::max());
> -        return instance;
> -    }
> -
> -    Velocity(const Quantity& value = Quantity()) : value(value)
> -    {
> -        if (value < Velocity::min())
> -            throw std::out_of_range("");
> -        if (value > Velocity::max())
> -            throw std::out_of_range("");
> -    }
> -
> -    inline bool operator==(const Velocity& rhs) const
> -    {
> -        return value == rhs.value;
> -    }
> -
> -    inline bool operator!=(const Velocity& rhs) const
> -    {
> -        return value != rhs.value;
> -    }
> -
> -    Quantity value;
> -};
> -
> -inline std::ostream& operator<<(std::ostream& out, const Velocity& velocity)
> -{
> -    out << "Velocity(" << velocity.value << ")";
> -    return out;
> -}
> -
> -template<>
> -struct AccuracyTraits<Velocity>
> -{
> -    static AccuracyLevel classify(const Velocity& h)
> -    {
> -        if (h.value > (1.f * units::MetersPerSecond))
> -            return AccuracyLevel::worst;
> -        
> -        if (h.value <= (1.f * units::MetersPerSecond))
> -            return AccuracyLevel::best;
> -
> -        return AccuracyLevel::worst;
> -    }
> -
> -    static Accuracy<Velocity> best()
> -    {
> -        return Accuracy<Velocity>{Velocity{Velocity::min()}};
> -    }
> -
> -    static Accuracy<Velocity> worst()
> -    {
> -        return Accuracy<Velocity>{Velocity{2*units::MetersPerSecond}};
> -    }
> -};
> +/** @brief Velocity is measured in m/s. */
> +typedef units::Quantity<units::Velocity> Velocity;
>  }
>  }
>  }
> 
> === modified file 'include/location_service/com/ubuntu/location/wgs84/altitude.h'
> --- include/location_service/com/ubuntu/location/wgs84/altitude.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/wgs84/altitude.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_ALTITUDE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_ALTITUDE_H_
>  
> -#include "com/ubuntu/location/units/units.h"
> -#include "com/ubuntu/location/wgs84/coordinate.h"
> +#include <com/ubuntu/location/units/units.h>
> +#include <com/ubuntu/location/wgs84/coordinate.h>
>  
>  namespace com
>  {
> 
> === modified file 'include/location_service/com/ubuntu/location/wgs84/coordinate.h'
> --- include/location_service/com/ubuntu/location/wgs84/coordinate.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/wgs84/coordinate.h	2014-06-24 16:02:38 +0000
> @@ -18,7 +18,7 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_COORDINATE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_COORDINATE_H_
>  
> -#include "com/ubuntu/location/units/units.h"
> +#include <com/ubuntu/location/units/units.h>
>  
>  #include <ostream>
>  
> @@ -39,12 +39,14 @@
>  };
>  
>  template<typename Tag, typename UnitType>
> -struct Coordinate
> +class Coordinate
>  {
> +public:
>      typedef UnitType Unit;
>      typedef units::Quantity<Unit> Quantity;
>  
> -    explicit Coordinate(const Quantity& value = Quantity()) : value(value)
> +    explicit Coordinate(const Quantity& value = Quantity())
> +        : value(value)
>      {
>          CoordinateTraits<Coordinate<Tag,UnitType>>::check_and_throw_if_invalid(value);
>      }
> 
> === modified file 'include/location_service/com/ubuntu/location/wgs84/latitude.h'
> --- include/location_service/com/ubuntu/location/wgs84/latitude.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/wgs84/latitude.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_LATITUDE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_LATITUDE_H_
>  
> -#include "com/ubuntu/location/units/units.h"
> -#include "com/ubuntu/location/wgs84/coordinate.h"
> +#include <com/ubuntu/location/units/units.h>
> +#include <com/ubuntu/location/wgs84/coordinate.h>
>  
>  #include <stdexcept>
>  
> 
> === modified file 'include/location_service/com/ubuntu/location/wgs84/longitude.h'
> --- include/location_service/com/ubuntu/location/wgs84/longitude.h	2013-05-28 14:41:06 +0000
> +++ include/location_service/com/ubuntu/location/wgs84/longitude.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,8 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_LONGITUDE_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_WGS84_LONGITUDE_H_
>  
> -#include "com/ubuntu/location/units/units.h"
> -#include "com/ubuntu/location/wgs84/coordinate.h"
> +#include <com/ubuntu/location/units/units.h>
> +#include <com/ubuntu/location/wgs84/coordinate.h>
>  
>  #include <stdexcept>
>  
> 
> === added file 'include/location_service/com/ubuntu/location/wifi_and_cell_reporting_state.h'
> --- include/location_service/com/ubuntu/location/wifi_and_cell_reporting_state.h	1970-01-01 00:00:00 +0000
> +++ include/location_service/com/ubuntu/location/wifi_and_cell_reporting_state.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_WIFI_AND_CELL_REPORTING_STATE_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_WIFI_AND_CELL_REPORTING_STATE_H_
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +enum class WifiAndCellIdReportingState
> +{
> +    on, ///< Wifi and Cell Ids might be reported to online location services.
> +    off ///< Wifi and Cell Ids are _not_ reported. This is the default value.
> +};
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_WIFI_AND_CELL_REPORTING_STATE_H_
> 
> === modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt'
> --- src/location_service/com/ubuntu/location/CMakeLists.txt	2014-01-31 11:08:33 +0000
> +++ src/location_service/com/ubuntu/location/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -1,19 +1,31 @@
> +if (${NET_CPP_FOUND})
> +  add_definitions(-DCOM_UBUNTU_LOCATION_SERVICE_HAVE_NET_CPP=1)
> +
> +  set(ICHNAEA_REPORTER_SRCS service/ichnaea_reporter.cpp)
> +endif (${NET_CPP_FOUND})
> +
>  add_subdirectory(providers)
>  
>  add_library(
>    ubuntu-location-service SHARED
>  
> +  ${UBUNTU_LOCATION_SERVICE_PUBLIC_HEADERS}
> +
>    default_provider_selection_policy.cpp
>    
> +  criteria.cpp
>    engine.cpp
>    init_and_shutdown.cpp
>    position.cpp
>    provider.cpp
>    provider_factory.cpp
>    proxy_provider.cpp
> +  set_name_for_thread.cpp
>  
>    service/default_configuration.cpp
>    service/default_permission_manager.cpp
> +  service/harvester.cpp
> +
>    service/implementation.cpp
>    service/skeleton.cpp
>    service/stub.cpp
> @@ -24,12 +36,38 @@
>    service/session/stub.cpp
>  
>    providers/config.cpp
> -)
> +
> +  ${ICHNAEA_REPORTER_SRCS}
> +)
> +
> +add_library(
> +  ubuntu-location-service-connectivity SHARED
> +
> +  set_name_for_thread.cpp
> +
> +  connectivity/radio_cell.cpp
> +  connectivity/wireless_network.cpp
> +  connectivity/ofono_nm_connectivity_manager.cpp
> +)
> +
> +set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map")
>  
>  set_target_properties(
>    ubuntu-location-service
>  
>    PROPERTIES
> +  LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}"
> +  LINK_DEPENDS ${symbol_map}
> +  VERSION ${UBUNTU_LOCATION_SERVICE_VERSION_MAJOR}.${UBUNTU_LOCATION_SERVICE_VERSION_MINOR}.${UBUNTU_LOCATION_SERVICE_VERSION_PATCH}
> +  SOVERSION ${UBUNTU_LOCATION_SERVICE_VERSION_MAJOR}
> +)
> +
> +set_target_properties(
> +  ubuntu-location-service-connectivity
> +
> +  PROPERTIES
> +  LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}"
> +  LINK_DEPENDS ${symbol_map}
>    VERSION ${UBUNTU_LOCATION_SERVICE_VERSION_MAJOR}.${UBUNTU_LOCATION_SERVICE_VERSION_MINOR}.${UBUNTU_LOCATION_SERVICE_VERSION_PATCH}
>    SOVERSION ${UBUNTU_LOCATION_SERVICE_VERSION_MAJOR}
>  )
> @@ -37,13 +75,30 @@
>  add_definitions(${ENABLED_PROVIDER_TARGETS_DEFINITIONS})
>  
>  target_link_libraries(
> +  ubuntu-location-service-connectivity
> +
> +  ${CMAKE_THREAD_LIBS_INIT}
> +  ${Boost_LIBRARIES}
> +  ${DBUS_LIBRARIES}
> +  ${DBUS_CPP_LDFLAGS}
> +  ${PROCESS_CPP_LDFLAGS}
> +  ${GLog_LIBRARY}
> +  ${GFlags_LIBRARY}
> +)
> +
> +target_link_libraries(
>    ubuntu-location-service
>  
> +  ubuntu-location-service-connectivity
> +
>    ${ENABLED_PROVIDER_TARGETS}
>  
> +  ${CMAKE_THREAD_LIBS_INIT}
>    ${Boost_LIBRARIES}
>    ${DBUS_LIBRARIES}
>    ${DBUS_CPP_LDFLAGS}
> +  ${JSON_CPP_LDFLAGS}
> +  ${NET_CPP_LDFLAGS}
>    ${GLog_LIBRARY}
>    ${GFlags_LIBRARY}
>  )
> @@ -53,21 +108,59 @@
>    DESTINATION ${CMAKE_INSTALL_LIBDIR}
>  )
>  
> +install(
> +  TARGETS ubuntu-location-service-connectivity
> +  DESTINATION ${CMAKE_INSTALL_LIBDIR}
> +)
> +
> +add_library(
> +  ubuntu-location-service-daemon
> +
> +  service/daemon.cpp
> +)
> +
>  add_executable(
>    ubuntu-location-serviced
>  
> -  service/main.cpp
> +  service/daemon_main.cpp
> +)
> +
> +add_executable(
> +  ubuntu-location-serviced-cli
> +
> +  service/daemon_cli_main.cpp
>  )
>  
>  target_link_libraries(
> -  ubuntu-location-serviced
> +  ubuntu-location-service-daemon
>  
>    ubuntu-location-service
> -
> -  ${ENABLED_PROVIDER_TARGETS}
> -
> -  ${Boost_LIBRARIES}
> -  ${DBUS_LIBRARIES}
> +)
> +
> +target_link_libraries(
> +  ubuntu-location-serviced
> +
> +  ubuntu-location-service-daemon
> +
> +  ${ENABLED_PROVIDER_TARGETS}
> +
> +  ${Boost_LIBRARIES}
> +  ${DBUS_LIBRARIES}
> +  ${DBUS_CPP_LIBRARIES}
> +  ${GLog_LIBRARY}
> +  ${GFlags_LIBRARY}
> +)
> +
> +target_link_libraries(
> +  ubuntu-location-serviced-cli
> +
> +  ubuntu-location-service-daemon
> +
> +  ${ENABLED_PROVIDER_TARGETS}
> +
> +  ${Boost_LIBRARIES}
> +  ${DBUS_LIBRARIES}
> +  ${DBUS_CPP_LIBRARIES}
>    ${GLog_LIBRARY}
>    ${GFlags_LIBRARY}
>  )
> @@ -77,3 +170,8 @@
>    DESTINATION ${CMAKE_INSTALL_BINDIR}
>  )
>  
> +install(
> +  TARGETS ubuntu-location-serviced-cli
> +  DESTINATION ${CMAKE_INSTALL_BINDIR}
> +)
> +
> 
> === added directory 'src/location_service/com/ubuntu/location/connectivity'
> === added file 'src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.h'
> --- src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/cached_radio_cell.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,489 @@
> +/*
> + * Copyright © 2012-2014 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef CACHED_RADIO_CELL_H_
> +#define CACHED_RADIO_CELL_H_
> +
> +#include <com/ubuntu/location/connectivity/radio_cell.h>
> +
> +#include "ofono.h"
> +
> +namespace
> +{
> +
> +struct CachedRadioCell : public com::ubuntu::location::connectivity::RadioCell
> +{
> +    typedef std::shared_ptr<CachedRadioCell> Ptr;
> +
> +    static const std::map<std::string, com::ubuntu::location::connectivity::RadioCell::Type>& type_lut()
> +    {
> +        static const std::map<std::string, com::ubuntu::location::connectivity::RadioCell::Type> lut
> +        {
> +            {
> +                org::Ofono::Manager::Modem::NetworkRegistration::Technology::gsm(),
> +                com::ubuntu::location::connectivity::RadioCell::Type::gsm
> +            },
> +            {
> +                org::Ofono::Manager::Modem::NetworkRegistration::Technology::lte(),
> +                com::ubuntu::location::connectivity::RadioCell::Type::lte
> +            },
> +            {
> +                org::Ofono::Manager::Modem::NetworkRegistration::Technology::umts(),
> +                com::ubuntu::location::connectivity::RadioCell::Type::umts
> +            },
> +            {
> +                org::Ofono::Manager::Modem::NetworkRegistration::Technology::edge(),
> +                com::ubuntu::location::connectivity::RadioCell::Type::unknown
> +            },
> +            {
> +                org::Ofono::Manager::Modem::NetworkRegistration::Technology::hspa(),
> +                com::ubuntu::location::connectivity::RadioCell::Type::unknown
> +            },
> +            {std::string(), com::ubuntu::location::connectivity::RadioCell::Type::unknown}
> +        };
> +
> +        return lut;
> +    };
> +
> +    CachedRadioCell(const org::Ofono::Manager::Modem& modem)
> +        : RadioCell(), radio_type(Type::gsm), modem(modem), detail{Gsm()}
> +    {
> +        auto technology =
> +                modem.network_registration.get<
> +                    org::Ofono::Manager::Modem::NetworkRegistration::Technology
> +                >();
> +
> +        auto it = type_lut().find(technology);
> +
> +        if (it == type_lut().end()) throw std::runtime_error
> +        {
> +            "Unknown technology for connected cell: " + technology
> +        };
> +
> +        if (it->second == com::ubuntu::location::connectivity::RadioCell::Type::unknown) throw std::runtime_error
> +        {
> +            "Unknown technology for connected cell: " + technology
> +        };
> +
> +        radio_type = it->second;
> +
> +        auto lac =
> +                modem.network_registration.get<
> +                    org::Ofono::Manager::Modem::NetworkRegistration::LocationAreaCode
> +                >();
> +
> +        int cell_id =
> +                modem.network_registration.get<
> +                    org::Ofono::Manager::Modem::NetworkRegistration::CellId
> +                >();
> +
> +        auto strength =
> +                modem.network_registration.get<
> +                    org::Ofono::Manager::Modem::NetworkRegistration::Strength
> +                >();
> +
> +        std::stringstream ssmcc
> +        {
> +            modem.network_registration.get<
> +                org::Ofono::Manager::Modem::NetworkRegistration::MobileCountryCode
> +            >()
> +        };
> +        int mcc{0}; ssmcc >> mcc;
> +        std::stringstream ssmnc
> +        {
> +            modem.network_registration.get<
> +                org::Ofono::Manager::Modem::NetworkRegistration::MobileNetworkCode
> +            >()
> +        };
> +        int mnc{0}; ssmnc >> mnc;
> +
> +        switch(radio_type)
> +        {
> +        case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +        {
> +            com::ubuntu::location::connectivity::RadioCell::Gsm gsm
> +            {
> +                com::ubuntu::location::connectivity::RadioCell::Gsm::MCC{mcc},
> +                com::ubuntu::location::connectivity::RadioCell::Gsm::MNC{mnc},
> +                com::ubuntu::location::connectivity::RadioCell::Gsm::LAC{lac},
> +                com::ubuntu::location::connectivity::RadioCell::Gsm::ID{cell_id},
> +                com::ubuntu::location::connectivity::RadioCell::Gsm::SignalStrength::from_percent(strength/100.f)
> +            };
> +            VLOG(1) << gsm;
> +            detail.gsm = gsm;
> +            break;
> +        }
> +        case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +        {
> +            com::ubuntu::location::connectivity::RadioCell::Lte lte
> +            {
> +                com::ubuntu::location::connectivity::RadioCell::Lte::MCC{mcc},
> +                com::ubuntu::location::connectivity::RadioCell::Lte::MNC{mnc},
> +                com::ubuntu::location::connectivity::RadioCell::Lte::TAC{lac},
> +                com::ubuntu::location::connectivity::RadioCell::Lte::ID{cell_id},
> +                com::ubuntu::location::connectivity::RadioCell::Lte::PID{},
> +                com::ubuntu::location::connectivity::RadioCell::Lte::SignalStrength::from_percent(strength/100.f)
> +            };
> +            VLOG(1) << lte;
> +            detail.lte = lte;
> +            break;
> +        }
> +        case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +        {
> +            com::ubuntu::location::connectivity::RadioCell::Umts umts
> +            {
> +                com::ubuntu::location::connectivity::RadioCell::Umts::MCC{mcc},
> +                com::ubuntu::location::connectivity::RadioCell::Umts::MNC{mnc},
> +                com::ubuntu::location::connectivity::RadioCell::Umts::LAC{lac},
> +                com::ubuntu::location::connectivity::RadioCell::Umts::ID{cell_id},
> +                com::ubuntu::location::connectivity::RadioCell::Umts::SignalStrength::from_percent(strength/100.f)
> +            };
> +            VLOG(1) << umts;
> +            detail.umts = umts;
> +            break;
> +        }
> +        default:
> +            break;
> +        }
> +
> +        modem.signals.property_changed->connect([this](const std::tuple<std::string, core::dbus::types::Variant>& tuple)
> +        {
> +            on_modem_property_changed(tuple);
> +        });
> +
> +        modem.network_registration.signals.property_changed->connect([this](const std::tuple<std::string, core::dbus::types::Variant>& tuple)
> +        {
> +            on_network_registration_property_changed(tuple);
> +        });
> +    }
> +
> +    const core::Signal<>& changed() const override
> +    {
> +        return on_changed;
> +    }
> +
> +    com::ubuntu::location::connectivity::RadioCell::Type type() const override
> +    {
> +        return radio_type;
> +    }
> +
> +    const com::ubuntu::location::connectivity::RadioCell::Gsm& gsm() const override
> +    {
> +        if (radio_type != com::ubuntu::location::connectivity::RadioCell::Type::gsm)
> +            throw std::runtime_error("Bad access to unset network type.");
> +
> +        return detail.gsm;
> +    }
> +
> +    const com::ubuntu::location::connectivity::RadioCell::Umts& umts() const override
> +    {
> +        if (radio_type != RadioCell::Type::umts)
> +            throw std::runtime_error("Bad access to unset network type.");
> +
> +        return detail.umts;
> +    }
> +
> +    const com::ubuntu::location::connectivity::RadioCell::Lte& lte() const override
> +    {
> +        if (radio_type != RadioCell::Type::lte)
> +            throw std::runtime_error("Bad access to unset network type.");
> +
> +        return detail.lte;
> +    }
> +
> +    void on_modem_property_changed(const std::tuple<std::string, core::dbus::types::Variant>& tuple)
> +    {
> +        VLOG(10) << "Property on modem " << modem.object->path() << " changed: " << std::get<0>(tuple);
> +    }
> +
> +    void on_network_registration_property_changed(const std::tuple<std::string, core::dbus::types::Variant>& tuple)
> +    {
> +        VLOG(10) << "Property changed on modem " << modem.object->path() << " for network registration: " << std::get<0>(tuple);
> +
> +        const auto& key = std::get<0>(tuple);
> +        const auto& variant = std::get<1>(tuple);
> +
> +        if (key == org::Ofono::Manager::Modem::NetworkRegistration::Technology::name())
> +        {
> +            auto value = variant.as<
> +                        org::Ofono::Manager::Modem::NetworkRegistration::Technology::ValueType
> +                    >();
> +
> +            auto it = type_lut().find(value);
> +
> +            if (it == type_lut().end())
> +            {
> +                LOG(WARNING) << "Unknown technology for connected cell: " << value;
> +                return;
> +            }
> +
> +            if (it->second == com::ubuntu::location::connectivity::RadioCell::Type::unknown)
> +            {
> +                LOG(WARNING) << "Unknown technology for connected cell: " + value;
> +                return;
> +            }
> +
> +            if (radio_type == it->second)
> +                return;
> +
> +            switch(radio_type)
> +            {
> +            case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                switch(it->second)
> +                {
> +                case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                    detail.umts.location_area_code = detail.gsm.location_area_code;
> +                    detail.umts.mobile_network_code = detail.gsm.mobile_network_code;
> +                    detail.umts.mobile_country_code = detail.gsm.mobile_country_code;
> +                    detail.umts.strength.reset();
> +                    detail.umts.id.reset();
> +                    break;
> +                case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                    detail.lte.tracking_area_code = detail.gsm.location_area_code;
> +                    detail.lte.mobile_network_code = detail.gsm.mobile_network_code;
> +                    detail.lte.mobile_country_code = detail.gsm.mobile_country_code;
> +                    detail.lte.strength.reset();
> +                    detail.lte.id.reset();
> +                    break;
> +                }
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                switch(it->second)
> +                {
> +                case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                    detail.gsm.location_area_code = detail.umts.location_area_code;
> +                    detail.gsm.mobile_network_code = detail.umts.mobile_network_code;
> +                    detail.gsm.mobile_country_code = detail.umts.mobile_country_code;
> +                    detail.gsm.strength.reset();
> +                    detail.gsm.id.reset();
> +                    break;
> +                case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                    detail.lte.tracking_area_code = detail.umts.location_area_code;
> +                    detail.lte.mobile_network_code = detail.umts.mobile_network_code;
> +                    detail.lte.mobile_country_code = detail.umts.mobile_country_code;
> +                    detail.lte.strength.reset();
> +                    detail.lte.id.reset();
> +                    break;
> +                }
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                switch(it->second)
> +                {
> +                case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                    detail.gsm.location_area_code = detail.lte.tracking_area_code;
> +                    detail.gsm.mobile_network_code = detail.lte.mobile_network_code;
> +                    detail.gsm.mobile_country_code = detail.lte.mobile_country_code;
> +                    detail.gsm.strength.reset();
> +                    detail.gsm.id.reset();
> +                    break;
> +                case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                    detail.umts.location_area_code = detail.lte.tracking_area_code;
> +                    detail.umts.mobile_network_code = detail.lte.mobile_network_code;
> +                    detail.umts.mobile_country_code = detail.lte.mobile_country_code;
> +                    detail.umts.strength.reset();
> +                    detail.umts.id.reset();
> +                    break;
> +                }
> +            default:
> +                break;
> +            };
> +
> +            radio_type = it->second;
> +            on_changed();
> +        }
> +
> +        if (key == org::Ofono::Manager::Modem::NetworkRegistration::CellId::name())
> +        {
> +            auto value = variant.as<
> +                        org::Ofono::Manager::Modem::NetworkRegistration::CellId::ValueType
> +                    >();
> +
> +            switch(radio_type)
> +            {
> +            case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                detail.gsm.id.set(value);
> +                VLOG(1) << detail.gsm;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                detail.umts.id.set(value);
> +                VLOG(1) << detail.umts;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                detail.lte.id.set(value);
> +                VLOG(1) << detail.lte;
> +                break;
> +            default:
> +                break;
> +            };
> +
> +            on_changed();
> +        }
> +
> +        if (key == org::Ofono::Manager::Modem::NetworkRegistration::LocationAreaCode::name())
> +        {
> +            auto value = variant.as<
> +                        org::Ofono::Manager::Modem::NetworkRegistration::LocationAreaCode::ValueType
> +                    >();
> +            switch(radio_type)
> +            {
> +            case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                detail.gsm.location_area_code.set(value);
> +                VLOG(1) << detail.gsm;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                detail.umts.location_area_code.set(value);
> +                VLOG(1) << detail.umts;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                detail.lte.tracking_area_code.set(value);
> +                VLOG(1) << detail.lte;
> +                break;
> +            default:
> +                break;
> +            };
> +
> +            on_changed();
> +        }
> +
> +        if (key == org::Ofono::Manager::Modem::NetworkRegistration::MobileCountryCode::name())
> +        {
> +            std::stringstream ss
> +            {
> +                variant.as<
> +                    org::Ofono::Manager::Modem::NetworkRegistration::MobileCountryCode::ValueType
> +                >()
> +            };
> +            int value{-1}; ss >> value;
> +
> +            switch(radio_type)
> +            {
> +            case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                detail.gsm.mobile_country_code.set(value);
> +                VLOG(1) << detail.gsm;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                detail.umts.mobile_country_code.set(value);
> +                VLOG(1) << detail.umts;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                detail.lte.mobile_country_code.set(value);
> +                VLOG(1) << detail.lte;
> +                break;
> +            default:
> +                break;
> +            };
> +
> +            on_changed();
> +        }
> +
> +        if (key == org::Ofono::Manager::Modem::NetworkRegistration::MobileNetworkCode::name())
> +        {
> +            std::stringstream ss
> +            {
> +                variant.as<
> +                    org::Ofono::Manager::Modem::NetworkRegistration::MobileNetworkCode::ValueType
> +                >()
> +            };
> +            int value{-1}; ss >> value;
> +
> +            switch(radio_type)
> +            {
> +            case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                detail.gsm.mobile_network_code.set(value);
> +                VLOG(1) << detail.gsm;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                detail.umts.mobile_network_code.set(value);
> +                VLOG(1) << detail.umts;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                detail.lte.mobile_network_code.set(value);
> +                VLOG(1) << detail.lte;
> +                break;
> +            default:
> +                break;
> +            };
> +
> +            on_changed();
> +        }
> +
> +        if (key == org::Ofono::Manager::Modem::NetworkRegistration::Strength::name())
> +        {
> +            auto value = variant.as<
> +                        org::Ofono::Manager::Modem::NetworkRegistration::Strength::ValueType
> +                    >();
> +
> +            switch(radio_type)
> +            {
> +            case com::ubuntu::location::connectivity::RadioCell::Type::gsm:
> +                detail.gsm.strength
> +                        = com::ubuntu::location::connectivity::RadioCell::Gsm::SignalStrength::from_percent(value/100.f);
> +                VLOG(1) << detail.gsm;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::umts:
> +                detail.umts.strength
> +                        = com::ubuntu::location::connectivity::RadioCell::Umts::SignalStrength::from_percent(value/100.f);
> +                VLOG(1) << detail.umts;
> +                break;
> +            case com::ubuntu::location::connectivity::RadioCell::Type::lte:
> +                detail.lte.strength
> +                        = com::ubuntu::location::connectivity::RadioCell::Lte::SignalStrength::from_percent(value/100.f);
> +                VLOG(1) << detail.lte;
> +                break;
> +            default:
> +                break;
> +            };
> +
> +            on_changed();
> +        }
> +    }
> +
> +    /** @cond */
> +    core::Signal<> on_changed;
> +    Type radio_type;
> +    org::Ofono::Manager::Modem modem;
> +
> +    struct None {};
> +
> +    union Detail
> +    {
> +        Detail() : none(None{})
> +        {
> +        }
> +
> +        Detail(const com::ubuntu::location::connectivity::RadioCell::Gsm& gsm) : gsm(gsm)
> +        {
> +        }
> +
> +        Detail(const com::ubuntu::location::connectivity::RadioCell::Umts& umts) : umts(umts)
> +        {
> +        }
> +
> +        Detail(const com::ubuntu::location::connectivity::RadioCell::Lte& lte) : lte(lte)
> +        {
> +        }
> +
> +        None none;
> +        Gsm gsm;
> +        Umts umts;
> +        Lte lte;
> +    } detail;
> +    /** @endcond */
> +};
> +}
> +
> +#endif // CACHED_RADIO_CELL_H_
> 
> === added file 'src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h'
> --- src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,218 @@
> +/*
> + * Copyright © 2012-2014 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef CACHED_WIRELESS_NETWORK_H_
> +#define CACHED_WIRELESS_NETWORK_H_
> +
> +#include <com/ubuntu/location/connectivity/wireless_network.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +
> +#include "nm.h"
> +
> +namespace
> +{
> +std::string utf8_ssid_to_string(const org::freedesktop::NetworkManager::AccessPoint::Ssid::ValueType& ssid)
> +{
> +    return std::string(ssid.begin(), ssid.end());
> +}
> +
> +com::ubuntu::location::connectivity::WirelessNetwork::Mode
> +wifi_mode_from_ap_mode(org::freedesktop::NetworkManager::AccessPoint::Mode::ValueType value)
> +{
> +    com::ubuntu::location::connectivity::WirelessNetwork::Mode mode
> +    {
> +        com::ubuntu::location::connectivity::WirelessNetwork::Mode::unknown
> +    };
> +
> +    switch (value)
> +    {
> +    case org::freedesktop::NetworkManager::AccessPoint::Mode::Value::unknown:
> +        mode = com::ubuntu::location::connectivity::WirelessNetwork::Mode::unknown;
> +        break;
> +    case org::freedesktop::NetworkManager::AccessPoint::Mode::Value::adhoc:
> +        mode = com::ubuntu::location::connectivity::WirelessNetwork::Mode::adhoc;
> +        break;
> +    case org::freedesktop::NetworkManager::AccessPoint::Mode::Value::infra:
> +        mode = com::ubuntu::location::connectivity::WirelessNetwork::Mode::infrastructure;
> +        break;
> +    }
> +
> +    return mode;
> +}
> +
> +struct CachedWirelessNetwork : public com::ubuntu::location::connectivity::WirelessNetwork
> +{
> +    typedef std::shared_ptr<CachedWirelessNetwork> Ptr;
> +
> +    const core::Property<std::chrono::system_clock::time_point>& last_seen() const override
> +    {
> +        return last_seen_;
> +    }
> +
> +    const core::Property<std::string>& bssid() const override
> +    {
> +        return bssid_;
> +    }
> +
> +    const core::Property<std::string>& ssid() const override
> +    {
> +        return ssid_;
> +    }
> +
> +    const core::Property<Mode>& mode() const override
> +    {
> +        return mode_;
> +    }
> +
> +    const core::Property<Frequency>& frequency() const override
> +    {
> +        return frequency_;
> +    }
> +
> +    const core::Property<SignalStrength>& signal_strength() const override
> +    {
> +        return signal_strength_;
> +    }
> +
> +    CachedWirelessNetwork(
> +            const org::freedesktop::NetworkManager::Device& device,
> +            const org::freedesktop::NetworkManager::AccessPoint& ap)
> +        : device_(device),
> +          access_point_(ap)
> +    {
> +        try
> +        {
> +            last_seen_ = std::chrono::system_clock::time_point
> +            {
> +                std::chrono::system_clock::duration{access_point_.last_seen->get()}
> +            };
> +        } catch(const std::exception& e)
> +        {
> +            LOG(WARNING) << e.what();
> +        }
> +
> +        bssid_ = access_point_.hw_address->get();
> +        ssid_ = utf8_ssid_to_string(access_point_.ssid->get());
> +        mode_ = wifi_mode_from_ap_mode(access_point_.mode->get());
> +        frequency_ = com::ubuntu::location::connectivity::WirelessNetwork::Frequency
> +        {
> +            access_point_.frequency->get()
> +        };
> +        signal_strength_ = com::ubuntu::location::connectivity::WirelessNetwork::SignalStrength
> +        {
> +            int(access_point_.strength->get())
> +        };
> +
> +        // Wire up all the connections
> +        access_point_.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
> +        {
> +            on_access_point_properties_changed(dict);
> +        });
> +    }
> +
> +    void on_access_point_properties_changed(const std::map<std::string, core::dbus::types::Variant>& dict)
> +    {
> +        // We route by string
> +        static const std::unordered_map<std::string, std::function<void(CachedWirelessNetwork&, const core::dbus::types::Variant&)> > lut
> +        {
> +            {
> +                org::freedesktop::NetworkManager::AccessPoint::HwAddress::name(),
> +                [](CachedWirelessNetwork& thiz, const core::dbus::types::Variant& value)
> +                {
> +                    thiz.bssid_ = value.as<org::freedesktop::NetworkManager::AccessPoint::HwAddress::ValueType>();
> +                }
> +            },
> +            {
> +                org::freedesktop::NetworkManager::AccessPoint::Ssid::name(),
> +                [](CachedWirelessNetwork& thiz, const core::dbus::types::Variant& value)
> +                {
> +                    thiz.ssid_ = utf8_ssid_to_string(value.as<org::freedesktop::NetworkManager::AccessPoint::Ssid::ValueType>());
> +                }
> +            },
> +            {
> +                org::freedesktop::NetworkManager::AccessPoint::Strength::name(),
> +                [](CachedWirelessNetwork& thiz, const core::dbus::types::Variant& value)
> +                {
> +                    thiz.signal_strength_ = com::ubuntu::location::connectivity::WirelessNetwork::SignalStrength
> +                    {
> +                        value.as<org::freedesktop::NetworkManager::AccessPoint::Strength::ValueType>()
> +                    };
> +                }
> +            },
> +            {
> +                org::freedesktop::NetworkManager::AccessPoint::Frequency::name(),
> +                [](CachedWirelessNetwork& thiz, const core::dbus::types::Variant& value)
> +                {
> +                    thiz.frequency_ = com::ubuntu::location::connectivity::WirelessNetwork::Frequency
> +                    {
> +                        value.as<org::freedesktop::NetworkManager::AccessPoint::Frequency::ValueType>()
> +                    };
> +                }
> +            },
> +            {
> +                org::freedesktop::NetworkManager::AccessPoint::Mode::name(),
> +                [](CachedWirelessNetwork& thiz, const core::dbus::types::Variant& value)
> +                {
> +                    thiz.mode_ = wifi_mode_from_ap_mode(value.as<org::freedesktop::NetworkManager::AccessPoint::Mode::ValueType>());
> +                }
> +            },
> +            {
> +                org::freedesktop::NetworkManager::AccessPoint::LastSeen::name(),
> +                [](CachedWirelessNetwork& thiz, const core::dbus::types::Variant& value)
> +                {
> +                    thiz.last_seen_ = std::chrono::system_clock::time_point
> +                    {
> +                        std::chrono::system_clock::duration
> +                        {
> +                            value.as<org::freedesktop::NetworkManager::AccessPoint::LastSeen::ValueType>()
> +                        }
> +                    };
> +                }
> +            }
> +        };
> +
> +        for (const auto& pair : dict)
> +        {
> +            VLOG(1) << "Properties on access point " << ssid_.get() << " changed: \n"
> +                    << "  " << pair.first;
> +
> +            // We do not treat failing property updates as fatal but instead just
> +            // log the issue for later analysis.
> +            try
> +            {
> +                if (lut.count(pair.first) > 0) lut.at(pair.first)(*this, pair.second);
> +            } catch (const std::exception& e)
> +            {
> +                LOG(WARNING) << "Exception while updating state for property change: " << pair.first;
> +            }
> +        }
> +    }
> +
> +    org::freedesktop::NetworkManager::Device device_;
> +    org::freedesktop::NetworkManager::AccessPoint access_point_;
> +
> +    core::Property<std::chrono::system_clock::time_point> last_seen_;
> +    core::Property<std::string> bssid_;
> +    core::Property<std::string> ssid_;
> +    core::Property<WirelessNetwork::Mode> mode_;
> +    core::Property<WirelessNetwork::Frequency> frequency_;
> +    core::Property<WirelessNetwork::SignalStrength> signal_strength_;
> +};
> +}
> +
> +#endif // CACHED_WIRELESS_NETWORK_H_
> 
> === added file 'src/location_service/com/ubuntu/location/connectivity/nm.h'
> --- src/location_service/com/ubuntu/location/connectivity/nm.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/nm.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,519 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_NM_H
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_NM_H
> +
> +#include <core/dbus/bus.h>
> +#include <core/dbus/object.h>
> +#include <core/dbus/property.h>
> +#include <core/dbus/service.h>
> +#include <core/dbus/types/object_path.h>
> +#include <core/dbus/types/struct.h>
> +#include <core/dbus/types/stl/map.h>
> +#include <core/dbus/types/stl/string.h>
> +#include <core/dbus/types/stl/tuple.h>
> +#include <core/dbus/types/stl/vector.h>
> +
> +namespace org
> +{
> +namespace freedesktop
> +{
> +struct NetworkManager
> +{
> +    typedef std::shared_ptr<NetworkManager> Ptr;
> +
> +    struct AccessPoint
> +    {
> +        static const std::string& name()
> +        {
> +            static const std::string s{"org.freedesktop.NetworkManager.AccessPoint"};
> +            return s;
> +        }
> +
> +        struct Frequency
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"Frequency"};
> +                return s;
> +            }
> +
> +            typedef AccessPoint Interface;
> +            typedef std::uint32_t ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +
> +        struct LastSeen
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"LastSeen"};
> +                return s;
> +            }
> +
> +            typedef AccessPoint Interface;
> +            typedef std::int32_t ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +
> +        struct Mode
> +        {
> +            enum Value
> +            {
> +                unknown = 0,
> +                adhoc = 1,
> +                infra = 2,
> +                ap = 3
> +            };
> +
> +            static const std::string& name()
> +            {
> +                static const std::string s{"Mode"};
> +                return s;
> +            }
> +
> +            typedef AccessPoint Interface;
> +            typedef std::uint32_t ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +
> +        struct HwAddress
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"HwAddress"};
> +                return s;
> +            }
> +
> +            typedef AccessPoint Interface;
> +            typedef std::string ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +
> +        struct Ssid
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"Ssid"};
> +                return s;
> +            }
> +
> +            typedef AccessPoint Interface;
> +            typedef std::vector<std::int8_t> ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +
> +        struct Strength
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"Strength"};
> +                return s;
> +            }
> +
> +            typedef AccessPoint Interface;
> +            typedef std::int8_t ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +
> +        struct PropertiesChanged
> +        {
> +            inline static std::string name()
> +            {
> +                return "PropertiesChanged";
> +            }
> +
> +            typedef AccessPoint Interface;
> +
> +            typedef std::map<std::string, core::dbus::types::Variant> ArgumentType;
> +        };
> +
> +        AccessPoint(const std::shared_ptr<core::dbus::Object>& object)
> +            : object(object),
> +              frequency(object->get_property<Frequency>()),
> +              last_seen(object->get_property<LastSeen>()),
> +              mode(object->get_property<Mode>()),
> +              hw_address(object->get_property<HwAddress>()),
> +              ssid(object->get_property<Ssid>()),
> +              strength(object->get_property<Strength>()),
> +              properties_changed(object->get_signal<PropertiesChanged>())
> +        {
> +        }
> +
> +        std::shared_ptr<core::dbus::Object> object;
> +        std::shared_ptr<core::dbus::Property<Frequency>> frequency;
> +        std::shared_ptr<core::dbus::Property<LastSeen>> last_seen;
> +        std::shared_ptr<core::dbus::Property<Mode>> mode;
> +        std::shared_ptr<core::dbus::Property<HwAddress>> hw_address;
> +        std::shared_ptr<core::dbus::Property<Ssid>> ssid;
> +        std::shared_ptr<core::dbus::Property<Strength>> strength;
> +        std::shared_ptr<core::dbus::Signal<PropertiesChanged, PropertiesChanged::ArgumentType>> properties_changed;
> +    };
> +
> +    struct Device
> +    {
> +        static const std::string& name()
> +        {
> +            static const std::string s{"org.freedesktop.NetworkManager.Device"};
> +            return s;
> +        }
> +
> +        enum class Type
> +        {
> +            unknown = 0,
> +            ethernet = 1,
> +            wifi = 2,
> +            unused_1 = 3,
> +            unused_2 = 4,
> +            bluetooth = 5,
> +            olpc_mesh = 6,
> +            wimax = 7,
> +            modem = 8,
> +            infiniband = 9,
> +            bond = 10,
> +            vlan = 11,
> +            adsl = 12,
> +            bridge = 13
> +        };
> +
> +        struct Wireless
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"org.freedesktop.NetworkManager.Device.Wireless"};
> +                return s;
> +            }
> +
> +            struct GetAccessPoints
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"GetAccessPoints"};
> +                    return s;
> +                }
> +
> +                typedef Wireless Interface;
> +
> +                static std::chrono::milliseconds default_timeout()
> +                {
> +                    return std::chrono::seconds{1};
> +                }
> +            };
> +
> +            struct RequestScan
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"RequestScan"};
> +                    return s;
> +                }
> +
> +                typedef Wireless Interface;
> +
> +                static std::chrono::milliseconds default_timeout()
> +                {
> +                    return std::chrono::seconds{1};
> +                }
> +            };
> +
> +            struct Signals
> +            {
> +                struct ScanDone
> +                {
> +                    inline static std::string name()
> +                    {
> +                        return "ScanDone";
> +                    }
> +
> +                    typedef Wireless Interface;
> +                    typedef void ArgumentType;
> +                };
> +
> +                struct AccessPointAdded
> +                {
> +                    inline static std::string name()
> +                    {
> +                        return "AccessPointAdded";
> +                    }
> +
> +                    typedef Wireless Interface;
> +
> +                    typedef core::dbus::types::ObjectPath ArgumentType;
> +                };
> +
> +                struct AccessPointRemoved
> +                {
> +                    inline static std::string name()
> +                    {
> +                        return "AccessPointRemoved";
> +                    }
> +
> +                    typedef Wireless Interface;
> +
> +                    typedef core::dbus::types::ObjectPath ArgumentType;
> +                };
> +            };
> +        };
> +
> +        struct DeviceType
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"DeviceType"};
> +                return s;
> +            }
> +
> +            typedef Device Interface;
> +            typedef std::uint32_t ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +
> +        Device(const std::shared_ptr<core::dbus::Service>& service,
> +               const std::shared_ptr<core::dbus::Object>& object)
> +            : service(service),
> +              object(object),
> +              device_type(object->get_property<DeviceType>()),
> +              signals
> +              {
> +                  object->get_signal<Wireless::Signals::ScanDone>(),
> +                  object->get_signal<Wireless::Signals::AccessPointAdded>(),
> +                  object->get_signal<Wireless::Signals::AccessPointRemoved>()
> +              }
> +        {
> +        }
> +
> +        Type type() const
> +        {
> +            return static_cast<Type>(device_type->get());
> +        }
> +
> +        void for_each_access_point(const std::function<void(const core::dbus::types::ObjectPath&)>& f) const
> +        {
> +            typedef std::vector<core::dbus::types::ObjectPath> ResultType;
> +            auto result = object->transact_method<Wireless::GetAccessPoints, ResultType>();
> +
> +            if (result.is_error())
> +                throw std::runtime_error(result.error().print());
> +
> +            for (const auto& path : result.value())
> +                f(path);
> +        }
> +
> +        std::vector<AccessPoint> get_access_points() const
> +        {
> +            typedef std::vector<core::dbus::types::ObjectPath> ResultType;
> +            auto result = object->invoke_method_synchronously<Wireless::GetAccessPoints, ResultType>();
> +
> +            if (result.is_error())
> +                throw std::runtime_error(result.error().print());
> +
> +            std::vector<AccessPoint> aps;
> +
> +            for (const auto& path : result.value())
> +                aps.push_back(AccessPoint(service->object_for_path(path)));
> +
> +            return aps;
> +        }
> +
> +        void request_scan() const
> +        {
> +            static const std::map<std::string, core::dbus::types::Variant> dictionary;
> +            auto result = object->invoke_method_asynchronously<Wireless::RequestScan, void>(dictionary);
> +        }
> +
> +        std::shared_ptr<core::dbus::Service> service;
> +        std::shared_ptr<core::dbus::Object> object;
> +        std::shared_ptr<core::dbus::Property<DeviceType>> device_type;
> +        struct
> +        {
> +            core::dbus::Signal<Wireless::Signals::ScanDone, Wireless::Signals::ScanDone::ArgumentType>::Ptr scan_done;
> +            core::dbus::Signal<Wireless::Signals::AccessPointAdded, Wireless::Signals::AccessPointAdded::ArgumentType>::Ptr ap_added;
> +            core::dbus::Signal<Wireless::Signals::AccessPointRemoved, Wireless::Signals::AccessPointRemoved::ArgumentType>::Ptr ap_removed;
> +        } signals;
> +    };
> +
> +    static const std::string& name()
> +    {
> +        static const std::string s{"org.freedesktop.NetworkManager"};
> +        return s;
> +    }
> +
> +    struct GetDevices
> +    {
> +        static const std::string& name()
> +        {
> +            static const std::string s{"GetDevices"};
> +            return s;
> +        }
> +
> +        typedef NetworkManager Interface;
> +
> +        static std::chrono::milliseconds default_timeout()
> +        {
> +            return std::chrono::seconds{1};
> +        }
> +    };
> +
> +    struct Properties
> +    {
> +        struct Connectivity
> +        {
> +            enum Values
> +            {
> +                unknown = 0,
> +                none = 1,
> +                portal = 2,
> +                limited = 3,
> +                full = 4
> +            };
> +
> +            static const std::string& name()
> +            {
> +                static const std::string s{"Connectivity"};
> +                return s;
> +            }
> +
> +            typedef NetworkManager Interface;
> +            typedef std::uint32_t ValueType;
> +            static const bool readable = true;
> +            static const bool writable = false;
> +        };
> +    };
> +
> +    struct Signals
> +    {
> +        struct DeviceAdded
> +        {
> +            inline static std::string name()
> +            {
> +                return "DeviceAdded";
> +            }
> +
> +            typedef NetworkManager Interface;
> +
> +            typedef core::dbus::types::ObjectPath ArgumentType;
> +        };
> +
> +        struct DeviceRemoved
> +        {
> +            inline static std::string name()
> +            {
> +                return "DeviceRemoved";
> +            }
> +
> +            typedef NetworkManager Interface;
> +
> +            typedef core::dbus::types::ObjectPath ArgumentType;
> +        };
> +
> +        struct PropertiesChanged
> +        {
> +            inline static std::string name()
> +            {
> +                return "PropertiesChanged";
> +            }
> +
> +            typedef NetworkManager Interface;
> +
> +            typedef std::map<std::string, core::dbus::types::Variant> ArgumentType;
> +        };
> +    };
> +
> +    NetworkManager(const core::dbus::Bus::Ptr& bus)
> +        : service(core::dbus::Service::use_service<NetworkManager>(bus)),
> +          object(service->object_for_path(core::dbus::types::ObjectPath("/org/freedesktop/NetworkManager"))),
> +          properties
> +          {
> +              object->get_property<Properties::Connectivity>()
> +          },
> +          signals
> +          {
> +              object->get_signal<Signals::DeviceAdded>(),
> +              object->get_signal<Signals::DeviceRemoved>(),
> +              object->get_signal<Signals::PropertiesChanged>()
> +          }
> +    {
> +    }
> +
> +    void for_each_device(const std::function<void(const core::dbus::types::ObjectPath&)>& f)
> +    {
> +        auto result =
> +                object->transact_method<
> +                    NetworkManager::GetDevices,
> +                    std::vector<core::dbus::types::ObjectPath>
> +                >();
> +
> +        if (result.is_error())
> +            throw std::runtime_error(result.error().print());
> +
> +        for (const auto& path : result.value())
> +            f(path);
> +    }
> +
> +    Device device_for_path(const core::dbus::types::ObjectPath& path)
> +    {
> +        return Device(service, service->object_for_path(path));
> +    }
> +
> +    std::vector<Device> get_devices()
> +    {
> +        auto result =
> +                object->invoke_method_synchronously<
> +                    NetworkManager::GetDevices,
> +                    std::vector<core::dbus::types::ObjectPath>>();
> +
> +        if (result.is_error())
> +            throw std::runtime_error(result.error().print());
> +
> +        std::vector<Device> devices;
> +        for (const auto& path : result.value())
> +        {
> +            devices.emplace_back(
> +                        Device(
> +                            service,
> +                            service->object_for_path(path)));
> +        }
> +
> +        return devices;
> +    }
> +
> +    std::shared_ptr<core::dbus::Service> service;
> +    std::shared_ptr<core::dbus::Object> object;
> +
> +    struct
> +    {
> +        std::shared_ptr<core::dbus::Property<Properties::Connectivity> > connectivity;
> +    } properties;
> +    struct
> +    {
> +        core::dbus::Signal<Signals::DeviceAdded, Signals::DeviceAdded::ArgumentType>::Ptr device_added;
> +        core::dbus::Signal<Signals::DeviceRemoved, Signals::DeviceRemoved::ArgumentType>::Ptr device_removed;
> +        core::dbus::Signal<Signals::PropertiesChanged, Signals::PropertiesChanged::ArgumentType>::Ptr properties_changed;
> +    } signals;
> +};
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_NM_H
> 
> === added file 'src/location_service/com/ubuntu/location/connectivity/ofono.h'
> --- src/location_service/com/ubuntu/location/connectivity/ofono.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/ofono.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,699 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_OFONO_H
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_OFONO_H
> +
> +#include <core/dbus/bus.h>
> +#include <core/dbus/object.h>
> +#include <core/dbus/property.h>
> +#include <core/dbus/service.h>
> +#include <core/dbus/types/object_path.h>
> +#include <core/dbus/types/struct.h>
> +#include <core/dbus/types/variant.h>
> +#include <core/dbus/types/stl/map.h>
> +#include <core/dbus/types/stl/string.h>
> +#include <core/dbus/types/stl/tuple.h>
> +#include <core/dbus/types/stl/vector.h>
> +
> +namespace org
> +{
> +struct Ofono
> +{
> +static const std::string& name()
> +{
> +    static const std::string s{"org.ofono"};
> +    return s;
> +}
> +struct Manager
> +{
> +    typedef std::shared_ptr<Manager> Ptr;
> +
> +    static const std::string& name()
> +    {
> +        static const std::string s{"org.ofono.Manager"};
> +        return s;
> +    }
> +
> +    struct GetModems
> +    {
> +        static const std::string& name()
> +        {
> +            static const std::string s{"GetModems"};
> +            return s;
> +        }
> +
> +        typedef Manager Interface;
> +        typedef std::vector<
> +            core::dbus::types::Struct<
> +                core::dbus::types::ObjectPath
> +            >
> +        > ResultType;
> +
> +        static std::chrono::milliseconds default_timeout()
> +        {
> +            return std::chrono::seconds{1};
> +        }
> +    };
> +
> +    struct ModemAdded
> +    {
> +        static const std::string& name()
> +        {
> +            static const std::string s{"ModemAdded"};
> +            return s;
> +        }
> +
> +        typedef Manager Interface;
> +        typedef std::tuple<core::dbus::types::ObjectPath, std::map<std::string, std::string>> ArgumentType;
> +    };
> +
> +    struct ModemRemoved
> +    {
> +        static const std::string& name()
> +        {
> +            static const std::string s{"ModemRemoved"};
> +            return s;
> +        }
> +
> +        typedef Manager Interface;
> +        typedef core::dbus::types::ObjectPath ArgumentType;
> +    };
> +
> +    struct Modem
> +    {
> +        static const std::string& name()
> +        {
> +            static const std::string s{"org.ofono.Modem"};
> +            return s;
> +        }
> +
> +        struct GetProperties
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"GetProperties"};
> +                return s;
> +            }
> +
> +            typedef Modem Interface;
> +            typedef std::map<std::string, core::dbus::types::Variant> ValueType;
> +
> +            static std::chrono::milliseconds default_timeout()
> +            {
> +                return std::chrono::seconds{1};
> +            }
> +        };
> +
> +        struct PropertyChanged
> +        {
> +            inline static std::string name()
> +            {
> +                return "PropertyChanged";
> +            }
> +
> +            typedef Modem Interface;
> +
> +            typedef std::tuple<std::string, core::dbus::types::Variant> ArgumentType;
> +        };
> +
> +        struct Properties
> +        {
> +            struct Powered
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Powered"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef bool ValueType;
> +                static const bool readable = true;
> +                static const bool writable = true;
> +            };
> +
> +            struct Online
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Online"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef bool ValueType;
> +                static const bool readable = true;
> +                static const bool writable = true;
> +            };
> +
> +            struct Lockdown
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Lockdown"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef bool ValueType;
> +                static const bool readable = true;
> +                static const bool writable = true;
> +            };
> +
> +            struct Name
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Name"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Manufacturer
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Manufacturer"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Model
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Model"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Revision
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Revision"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Serial
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Serial"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Features
> +            {
> +                static constexpr const char* net{"net"};
> +                static constexpr const char* rat{"rat"};
> +                static constexpr const char* cbs{"cbs"};
> +                static constexpr const char* sms{"sms"};
> +                static constexpr const char* sim{"sim"};
> +                static constexpr const char* stk{"stk"};
> +                static constexpr const char* ussd{"ussd"};
> +                static constexpr const char* gprs{"gprs"};
> +                static constexpr const char* tty{"tty"};
> +                static constexpr const char* gps{"gps"};
> +
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Features"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::vector<std::string> ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Interfaces
> +            {
> +                static constexpr const char* assisted_satellite_navigation
> +                {
> +                    "org.ofono.AssistedSatelliteNavigation"
> +                };
> +                static constexpr const char* audio_settings
> +                {
> +                    "org.ofono.AudioSettings"
> +                };
> +                static constexpr const char* call_barring
> +                {
> +                    "org.ofono.CallBarring"
> +                };
> +                static constexpr const char* call_forwarding
> +                {
> +                    "org.ofono.CallForwarding"
> +                };
> +                static constexpr const char* call_meter
> +                {
> +                    "org.ofono.CallMeter"
> +                };
> +                static constexpr const char* call_settings
> +                {
> +                    "org.ofono.CallSettings"
> +                };
> +                static constexpr const char* call_volume
> +                {
> +                    "org.ofono.CallVolume"
> +                };
> +                static constexpr const char* cell_broadcast
> +                {
> +                    "org.ofono.CellBroadcast"
> +                };
> +                static constexpr const char* hands_free
> +                {
> +                    "org.ofono.Handsfree"
> +                };
> +                static constexpr const char* location_reporting
> +                {
> +                    "org.ofono.LocationReporting"
> +                };
> +                static constexpr const char* message_manager
> +                {
> +                    "org.ofono.MessageManager"
> +                };
> +                static constexpr const char* message_waiting
> +                {
> +                    "org.ofono.MessageWaiting"
> +                };
> +                static constexpr const char* network_registration
> +                {
> +                    "org.ofono.NetworkRegistration"
> +                };
> +                static constexpr const char* phonebook
> +                {
> +                    "org.ofono.Phonebook"
> +                };
> +                static constexpr const char* push_notification
> +                {
> +                    "org.ofono.PushNotification"
> +                };
> +                static constexpr const char* radio_settings
> +                {
> +                    "org.ofono.RadioSettings"
> +                };
> +                static constexpr const char* sim_manager
> +                {
> +                    "org.ofono.SimManager"
> +                };
> +                static constexpr const char* smart_messaging
> +                {
> +                    "org.ofono.SmartMessaging"
> +                };
> +                static constexpr const char* sim_toolkit
> +                {
> +                    "org.ofono.SimToolkit"
> +                };
> +                static constexpr const char* supplementary_services
> +                {
> +                    "org.ofono.SupplementaryServices"
> +                };
> +                static constexpr const char* text_telephony
> +                {
> +                    "org.ofono.TextTelephony"
> +                };
> +                static constexpr const char* voice_call_manager
> +                {
> +                    "org.ofono.VoiceCallManager"
> +                };
> +
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Interfaces"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::vector<std::string> ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Type
> +            {
> +                static constexpr const char* test{"test"};
> +                static constexpr const char* hfp{"hfp"};
> +                static constexpr const char* sap{"sap"};
> +                static constexpr const char* hardware{"hardware"};
> +
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Type"};
> +                    return s;
> +                }
> +
> +                typedef Modem Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +        };
> +
> +        struct NetworkRegistration
> +        {
> +            static const std::string& name()
> +            {
> +                static const std::string s{"org.ofono.NetworkRegistration"};
> +                return s;
> +            }            
> +
> +            struct GetProperties
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"GetProperties"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::map<std::string, core::dbus::types::Variant> ValueType;
> +
> +                static std::chrono::milliseconds default_timeout()
> +                {
> +                    return std::chrono::seconds{1};
> +                }
> +            };
> +
> +            struct PropertyChanged
> +            {
> +                inline static std::string name()
> +                {
> +                    return "PropertyChanged";
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +
> +                typedef std::tuple<std::string, core::dbus::types::Variant> ArgumentType;
> +            };
> +
> +            struct Status
> +            {
> +                enum class Value
> +                {
> +                    unregistered,
> +                    registered,
> +                    searching,
> +                    denied,
> +                    unknown,
> +                    roaming
> +                };
> +
> +                static constexpr const char* unregistered
> +                {
> +                    "unregistered"
> +                };
> +                static constexpr const char* registered
> +                {
> +                    "registered"
> +                };
> +                static constexpr const char* searching
> +                {
> +                    "searching"
> +                };
> +                static constexpr const char* denied
> +                {
> +                    "denied"
> +                };
> +                static constexpr const char* unknown
> +                {
> +                    "unknown"
> +                };
> +                static constexpr const char* roaming
> +                {
> +                    "roaming"
> +                };
> +
> +                static const char* value_to_string(Value value)
> +                {
> +                    switch (value)
> +                    {
> +                    case Value::unregistered: return unregistered;
> +                    case Value::registered: return registered;
> +                    case Value::searching: return searching;
> +                    case Value::denied: return denied;
> +                    case Value::unknown: return unknown;
> +                    case Value::roaming: return roaming;
> +                    }
> +
> +                    return nullptr;
> +                }
> +
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Status"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct LocationAreaCode
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"LocationAreaCode"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::uint16_t ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct CellId
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"CellId"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::uint32_t ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct MobileCountryCode
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"MobileCountryCode"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct MobileNetworkCode
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"MobileNetworkCode"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Technology
> +            {
> +                static const char* gsm() { return "gsm"; }
> +                static const char* edge() { return "edge"; }
> +                static const char* umts() { return "umts"; }
> +                static const char* hspa() { return "hspa"; }
> +                static const char* lte() { return "lte"; }
> +
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Technology"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::string ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            struct Strength
> +            {
> +                static const std::string& name()
> +                {
> +                    static const std::string s{"Strength"};
> +                    return s;
> +                }
> +
> +                typedef NetworkRegistration Interface;
> +                typedef std::int8_t ValueType;
> +                static const bool readable = true;
> +                static const bool writable = false;
> +            };
> +
> +            NetworkRegistration(const std::shared_ptr<core::dbus::Object>& object)
> +                : object(object),
> +                  signals
> +                  {
> +                      object->get_signal<PropertyChanged>()
> +                  }
> +            {
> +                refresh_properties();
> +            }
> +
> +            void refresh_properties() const
> +            {
> +                auto result = object->invoke_method_synchronously<GetProperties, GetProperties::ValueType>();
> +                if (result.is_error())
> +                    throw std::runtime_error(result.error().print());
> +
> +                properties = result.value();
> +            }
> +
> +            template<typename Property>
> +            typename Property::ValueType get() const
> +            {
> +                refresh_properties();
> +
> +                auto it = properties.find(Property::name());
> +
> +                if (it == properties.end())
> +                {
> +                    LOG(WARNING) << "Could not find property for name " << Property::name();
> +                    return typename Property::ValueType{};
> +                }
> +
> +                return it->second.template as<typename Property::ValueType>();
> +            }
> +
> +            std::shared_ptr<core::dbus::Object> object;
> +            mutable GetProperties::ValueType properties;
> +
> +            struct
> +            {
> +                core::dbus::Signal<PropertyChanged, PropertyChanged::ArgumentType>::Ptr property_changed;
> +            } signals;
> +        };
> +
> +        Modem(const std::shared_ptr<core::dbus::Service>& service,
> +              const std::shared_ptr<core::dbus::Object>& object)
> +            : service(service),
> +              object(object),
> +              signals
> +              {
> +                  object->get_signal<PropertyChanged>()
> +              },
> +              network_registration{object}
> +        {
> +        }
> +
> +        std::shared_ptr<core::dbus::Service> service;
> +        std::shared_ptr<core::dbus::Object> object;
> +
> +        struct
> +        {
> +            core::dbus::Signal<PropertyChanged, PropertyChanged::ArgumentType>::Ptr property_changed;
> +        } signals;
> +
> +        NetworkRegistration network_registration;
> +    };
> +
> +    Manager(const core::dbus::Bus::Ptr& bus)
> +        : service(core::dbus::Service::use_service<org::Ofono>(bus)),
> +          object(service->object_for_path(core::dbus::types::ObjectPath("/"))),
> +          signals
> +          {
> +              object->get_signal<ModemAdded>(),
> +              object->get_signal<ModemRemoved>()
> +          }
> +    {
> +    }
> +
> +    Modem modem_for_path(const core::dbus::types::ObjectPath& path) const
> +    {
> +        return Modem
> +        {
> +            service,
> +            service->object_for_path(path)
> +        };
> +    }
> +
> +    void for_each_modem(const std::function<void(const core::dbus::types::ObjectPath&)>& functor) const
> +    {
> +        auto result = object->invoke_method_synchronously<GetModems, GetModems::ResultType>();
> +
> +        if (result.is_error())
> +            throw std::runtime_error(result.error().print());
> +
> +        for (const auto& element : result.value())
> +        {
> +            functor(element.value);
> +        }
> +    }
> +
> +    std::shared_ptr<core::dbus::Service> service;
> +    std::shared_ptr<core::dbus::Object> object;
> +
> +    struct
> +    {
> +        std::shared_ptr<core::dbus::Signal<ModemAdded, ModemAdded::ArgumentType>> modem_added;
> +        std::shared_ptr<core::dbus::Signal<ModemRemoved, ModemRemoved::ArgumentType>> modem_removed;
> +    } signals;
> +};
> +};
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_CONNECTIVITY_OFONO_H
> 
> === added file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp'
> --- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,404 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include "ofono_nm_connectivity_manager.h"
> +
> +namespace connectivity = com::ubuntu::location::connectivity;
> +namespace dbus = core::dbus;
> +namespace xdg = org::freedesktop;
> +namespace
> +{
> +connectivity::State from_nm_property(std::uint32_t value)
> +{
> +    connectivity::State result{connectivity::State::unknown};
> +
> +    switch (value)
> +    {
> +    case xdg::NetworkManager::Properties::Connectivity::Values::unknown:
> +        result = connectivity::State::unknown;
> +        break;
> +    case xdg::NetworkManager::Properties::Connectivity::Values::none:
> +        result = connectivity::State::none;
> +        break;
> +    case xdg::NetworkManager::Properties::Connectivity::Values::portal:
> +        result = connectivity::State::portal;
> +        break;
> +    case xdg::NetworkManager::Properties::Connectivity::Values::limited:
> +        result = connectivity::State::limited;
> +        break;
> +    case xdg::NetworkManager::Properties::Connectivity::Values::full:
> +        result = connectivity::State::full;
> +        break;
> +    }
> +
> +    return result;
> +}
> +}
> +
> +const core::Property<connectivity::State>& impl::OfonoNmConnectivityManager::state() const
> +{
> +    return d.state;
> +}
> +
> +void impl::OfonoNmConnectivityManager::request_scan_for_wireless_networks()
> +{
> +    std::lock_guard<std::mutex> lg(d.cached.guard);
> +
> +    for (const auto& pair : d.cached.wireless_devices)
> +        pair.second.request_scan();
> +}
> +
> +const core::Signal<>& impl::OfonoNmConnectivityManager::wireless_network_scan_finished() const
> +{
> +    return d.signals.wireless_network_scan_finished;
> +}
> +
> +const core::Signal<connectivity::WirelessNetwork::Ptr>& impl::OfonoNmConnectivityManager::wireless_network_added() const
> +{
> +    return d.signals.wireless_network_added;
> +}
> +
> +const core::Signal<connectivity::WirelessNetwork::Ptr>& impl::OfonoNmConnectivityManager::wireless_network_removed() const
> +{
> +    return d.signals.wireless_network_removed;
> +}
> +
> +void impl::OfonoNmConnectivityManager::enumerate_visible_wireless_networks(const std::function<void(const connectivity::WirelessNetwork::Ptr&)>& f) const
> +{
> +    std::lock_guard<std::mutex> lg(d.cached.guard);
> +    for (const auto& wifi : d.cached.wifis)
> +        f(wifi.second);
> +}
> +
> +const core::Signal<connectivity::RadioCell::Ptr>& impl::OfonoNmConnectivityManager::connected_cell_added() const
> +{
> +    return d.signals.connected_cell_added;
> +}
> +
> +const core::Signal<connectivity::RadioCell::Ptr>& impl::OfonoNmConnectivityManager::connected_cell_removed() const
> +{
> +    return d.signals.connected_cell_removed;
> +}
> +
> +void impl::OfonoNmConnectivityManager::enumerate_connected_radio_cells(const std::function<void(const connectivity::RadioCell::Ptr&)>& f) const
> +{
> +    std::lock_guard<std::mutex> lg(d.cached.guard);
> +    for (const auto& cell : d.cached.cells)
> +        f(cell.second);
> +}
> +
> +impl::OfonoNmConnectivityManager::Private::Private()
> +{
> +    try
> +    {
> +        system_bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::system);
> +        executor = dbus::asio::make_executor(system_bus);
> +        system_bus->install_executor(executor);
> +
> +        worker = std::move(std::thread
> +        {
> +           [this]()
> +           {
> +               system_bus->run();
> +           }
> +        });
> +
> +        setup_network_stack_access();
> +        setup_radio_stack_access();
> +    }
> +    catch (const std::exception& e)
> +    {
> +        LOG(ERROR) << "Error while setting up access to radio and network stack: " << e.what();
> +    }
> +}
> +
> +impl::OfonoNmConnectivityManager::Private::~Private()
> +{
> +    if (system_bus)
> +        system_bus->stop();
> +
> +    if (worker.joinable())
> +        worker.join();
> +}
> +
> +void impl::OfonoNmConnectivityManager::Private::setup_radio_stack_access()
> +{
> +    modem_manager.reset(new org::Ofono::Manager(system_bus));
> +
> +    modem_manager->for_each_modem([this](const core::dbus::types::ObjectPath& path)
> +    {
> +        try
> +        {
> +            on_modem_added(path);
> +        }
> +        catch(const std::runtime_error& e)
> +        {
> +            LOG(WARNING) << "Exception while creating connected radio cell: " << e.what();
> +        }
> +    });
> +
> +    modem_manager->signals.modem_added->connect([this](const org::Ofono::Manager::ModemAdded::ArgumentType& arg)
> +    {
> +        try
> +        {
> +            on_modem_added(std::get<0>(arg));
> +        }
> +        catch(const std::exception& e)
> +        {
> +            LOG(WARNING) << "Exception while adding modem: " << e.what();
> +        }
> +    });
> +
> +    modem_manager->signals.modem_removed->connect([this](const core::dbus::types::ObjectPath& path)
> +    {
> +        try
> +        {
> +            on_modem_removed(path);
> +        }
> +        catch(const std::exception& e)
> +        {
> +            LOG(WARNING) << "Exception while removing modem: " << e.what();
> +        }
> +    });
> +}
> +
> +void impl::OfonoNmConnectivityManager::Private::on_modem_added(const core::dbus::types::ObjectPath& path)
> +{
> +    auto modem = modem_manager->modem_for_path(path);
> +
> +    // We first wire up to property changes here.
> +    modem.signals.property_changed->connect([this, path](const std::tuple<std::string, core::dbus::types::Variant>& tuple)
> +    {
> +        const auto& key = std::get<0>(tuple); VLOG(10) << "Property changed for modem: " << key;
> +
> +        if (org::Ofono::Manager::Modem::Properties::Interfaces::name() == key)
> +        {
> +            auto interfaces = std::get<1>(tuple).as<std::vector<std::string> >();
> +            if (VLOG_IS_ON(10)) for(const auto& interface : interfaces) VLOG(10) << interface;
> +            on_modem_interfaces_changed(path, interfaces);
> +        }
> +
> +    });
> +
> +    // And update our cache of modems and registered cells.
> +    auto cell = std::make_shared<CachedRadioCell>(modem);
> +    {
> +        std::lock_guard<std::mutex> lg(cached.guard);
> +        cached.modems.insert(std::make_pair(modem.object->path(), modem));
> +        cached.cells.insert(std::make_pair(modem.object->path(), cell));
> +    }
> +    // Announce the newly added cell to API customers, without the lock
> +    // on the cache being held.
> +    signals.connected_cell_added(cell);
> +}
> +
> +void impl::OfonoNmConnectivityManager::Private::on_modem_removed(const core::dbus::types::ObjectPath& path)
> +{
> +    CachedRadioCell::Ptr cell;
> +    {
> +        std::lock_guard<std::mutex> lg(cached.guard);
> +
> +        // Update modem and cell cache.
> +        auto itc = cached.cells.find(path);
> +        auto itm = cached.modems.find(path);
> +
> +        if (itc != cached.cells.end())
> +        {
> +            cell = itc->second;
> +            cached.cells.erase(itc);
> +        }
> +
> +        if (itm != cached.modems.end())
> +        {
> +            cached.modems.erase(path);
> +        }
> +    }
> +    // Inform customers of the registered cell being removed, without
> +    // the lock on the cache being held.
> +    if (cell) signals.connected_cell_removed(cell);
> +}
> +
> +void impl::OfonoNmConnectivityManager::Private::on_modem_interfaces_changed(
> +        const core::dbus::types::ObjectPath& path,
> +        const std::vector<std::string>& interfaces)
> +{
> +    std::unique_lock<std::mutex> ul(cached.guard);
> +
> +    auto itm = cached.modems.find(path);
> +    if (itm == cached.modems.end())
> +    {
> +        LOG(WARNING) << "Could not find a modem for path " << path.as_string();
> +        return;
> +    }
> +
> +    auto itt = cached.cells.find(path);
> +    const bool has_cell_for_modem = itt != cached.cells.end();
> +
> +    auto it = std::find(
> +                interfaces.begin(),
> +                interfaces.end(),
> +                std::string{org::Ofono::Manager::Modem::Properties::Interfaces::network_registration});
> +    const bool modem_has_network_registration = it != interfaces.end();
> +
> +    if (has_cell_for_modem and not modem_has_network_registration)
> +    {
> +        // A network registration was lost and we remove the corresponding
> +        // cell instance from the cache.
> +        auto cell = itt->second;
> +        cached.cells.erase(itt);
> +
> +        // Cache is up to date now and we announce the removal of the cell
> +        // to API customers, with the lock on the cache not being held.
> +        ul.unlock(); signals.connected_cell_removed(cell);
> +    } else if (not has_cell_for_modem and modem_has_network_registration)
> +    {
> +        // A new network registration is coming in and we have to create
> +        // a corresponding cell instance.
> +        auto cell = std::make_shared<CachedRadioCell>(itm->second);
> +        cached.cells.insert(std::make_pair(path,cell));
> +        // Cache is up to date now and we announce the new cell to
> +        // API customers, with the lock on the cache not being held.
> +        ul.unlock(); signals.connected_cell_added(cell);
> +    }
> +}
> +
> +void impl::OfonoNmConnectivityManager::Private::setup_network_stack_access()
> +{
> +    network_manager.reset(new xdg::NetworkManager(system_bus));
> +
> +    network_manager->for_each_device([this](const core::dbus::types::ObjectPath& device_path)
> +    {
> +        auto device = network_manager->device_for_path(device_path);
> +
> +        if (device.type() == xdg::NetworkManager::Device::Type::wifi)
> +        {
> +            // Make the device known to the cache.
> +            cached.wireless_devices.insert(std::make_pair(device_path, device));
> +
> +            // Iterate over all currently known wifis
> +            device.for_each_access_point([this, device_path](const core::dbus::types::ObjectPath& path)
> +            {
> +                try
> +                {
> +                    on_access_point_added(path, device_path);
> +                }
> +                catch (const std::exception& e)
> +                {
> +                    LOG(ERROR) << "Error while creating ap/wifi: " << e.what();
> +                }
> +            });
> +
> +            device.signals.scan_done->connect([this]()
> +            {
> +                signals.wireless_network_scan_finished();
> +            });
> +
> +            device.signals.ap_added->connect([this, device_path](const core::dbus::types::ObjectPath& path)
> +            {
> +                try
> +                {
> +                    on_access_point_added(path, device_path);
> +                }
> +                catch (const std::exception& e)
> +                {
> +                    LOG(ERROR) << "Error while creating ap/wifi: " << e.what();
> +                }
> +            });
> +
> +            device.signals.ap_removed->connect([this](const core::dbus::types::ObjectPath& path)
> +            {
> +                try
> +                {
> +                    on_access_point_removed(path);
> +                }
> +                catch (const std::exception& e)
> +                {
> +                    LOG(ERROR) << "Error while removing ap/wifi: " << e.what();
> +                }
> +            });
> +        }
> +    });
> +
> +    // Query the initial connectivity state
> +    state.set(from_nm_property(network_manager->properties.connectivity->get()));
> +
> +    // And we wire up to property changes here
> +    network_manager->signals.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
> +    {
> +        for (const auto& pair : dict)
> +        {
> +            VLOG(1) << "Property has changed: " << std::endl
> +                    << "  " << pair.first;
> +
> +            if (xdg::NetworkManager::Properties::Connectivity::name() == pair.first)
> +            {
> +                state.set(from_nm_property(pair.second.as<xdg::NetworkManager::Properties::Connectivity::ValueType>()));
> +            }
> +        }
> +    });
> +}
> +
> +void impl::OfonoNmConnectivityManager::Private::on_access_point_added(
> +        const core::dbus::types::ObjectPath& ap_path,
> +        const core::dbus::types::ObjectPath& device_path)
> +{
> +    std::unique_lock<std::mutex> ul(cached.guard);
> +
> +    // Let's see if we have a device known for the path. We return early
> +    // if we do not know about the device.
> +    auto itd = cached.wireless_devices.find(device_path);
> +    if (itd == cached.wireless_devices.end())
> +        return;
> +
> +    xdg::NetworkManager::AccessPoint ap
> +    {
> +        network_manager->service->add_object_for_path(ap_path)
> +    };
> +
> +    auto wifi = std::make_shared<CachedWirelessNetwork>(itd->second, ap);
> +    cached.wifis[ap_path] = wifi;
> +
> +    // Let API consumers know that an AP appeared. The lock on the cache is
> +    // not held to prevent from deadlocks.
> +    ul.unlock(); signals.wireless_network_added(wifi);
> +}
> +
> +void impl::OfonoNmConnectivityManager::Private::on_access_point_removed(const core::dbus::types::ObjectPath& ap_path)
> +{
> +    std::unique_lock<std::mutex> ul(cached.guard);
> +
> +    // Let's see if we know about the wifi. We return early if not.
> +    auto itw = cached.wifis.find(ap_path);
> +    if (itw == cached.wifis.end())
> +        return;
> +
> +    // Update the cache and keep the wifi object alive until API consumers
> +    // have been informed of the wifi going away.
> +    connectivity::WirelessNetwork::Ptr wifi = itw->second;
> +    cached.wifis.erase(itw);
> +
> +    // Let API consumers know that an AP disappeared. The lock on the cache is
> +    // not held to prevent from deadlocks.
> +    ul.unlock(); signals.wireless_network_removed(wifi);
> +}
> +
> +const std::shared_ptr<connectivity::Manager>& connectivity::platform_default_manager()
> +{
> +    static const std::shared_ptr<connectivity::Manager> instance{new impl::OfonoNmConnectivityManager{}};
> +    return instance;
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h'
> --- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,114 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#ifndef OFONO_NM_CONNECTIVITY_MANAGER_H_
> +#define OFONO_NM_CONNECTIVITY_MANAGER_H_
> +
> +#include <com/ubuntu/location/connectivity/manager.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +
> +#include "cached_radio_cell.h"
> +#include "cached_wireless_network.h"
> +#include "nm.h"
> +#include "ofono.h"
> +
> +#include <core/dbus/bus.h>
> +#include <core/dbus/object.h>
> +#include <core/dbus/property.h>
> +#include <core/dbus/service.h>
> +#include <core/dbus/types/object_path.h>
> +#include <core/dbus/types/struct.h>
> +#include <core/dbus/types/stl/map.h>
> +#include <core/dbus/types/stl/string.h>
> +#include <core/dbus/types/stl/tuple.h>
> +#include <core/dbus/types/stl/vector.h>
> +
> +#include <core/dbus/asio/executor.h>
> +
> +#include "../set_name_for_thread.h"
> +
> +#include <chrono>
> +
> +namespace dbus = core::dbus;
> +
> +namespace impl
> +{
> +struct OfonoNmConnectivityManager : public com::ubuntu::location::connectivity::Manager
> +{
> +    const core::Property<com::ubuntu::location::connectivity::State>& state() const override;
> +
> +    void request_scan_for_wireless_networks() override;
> +
> +    const core::Signal<>& wireless_network_scan_finished() const override;
> +    const core::Signal<com::ubuntu::location::connectivity::WirelessNetwork::Ptr>& wireless_network_added() const override;
> +    const core::Signal<com::ubuntu::location::connectivity::WirelessNetwork::Ptr>& wireless_network_removed() const override;
> +
> +    void enumerate_visible_wireless_networks(const std::function<void(const com::ubuntu::location::connectivity::WirelessNetwork::Ptr&)>& f) const override;
> +
> +    const core::Signal<com::ubuntu::location::connectivity::RadioCell::Ptr>& connected_cell_added() const override;
> +    const core::Signal<com::ubuntu::location::connectivity::RadioCell::Ptr>& connected_cell_removed() const override;
> +
> +    void enumerate_connected_radio_cells(const std::function<void(const com::ubuntu::location::connectivity::RadioCell::Ptr&)>& f) const override;
> +
> +    struct Private
> +    {
> +        Private();
> +        ~Private();
> +
> +        void setup_radio_stack_access();
> +        void on_modem_added(const core::dbus::types::ObjectPath& path);
> +        void on_modem_removed(const core::dbus::types::ObjectPath& path);
> +        void on_modem_interfaces_changed(const core::dbus::types::ObjectPath& path, const std::vector<std::string>& interfaces);
> +
> +        void setup_network_stack_access();
> +        void on_access_point_added(const core::dbus::types::ObjectPath& ap_path, const core::dbus::types::ObjectPath& device_path);
> +        void on_access_point_removed(const core::dbus::types::ObjectPath& ap_path);
> +
> +        core::dbus::Bus::Ptr system_bus;
> +        core::dbus::Executor::Ptr executor;
> +
> +        std::thread worker;
> +
> +        org::freedesktop::NetworkManager::Ptr network_manager;
> +        org::Ofono::Manager::Ptr modem_manager;
> +
> +        struct
> +        {
> +            mutable std::mutex guard;
> +            std::map<core::dbus::types::ObjectPath, CachedRadioCell::Ptr> cells;
> +            std::map<core::dbus::types::ObjectPath, org::Ofono::Manager::Modem> modems;
> +            std::map<core::dbus::types::ObjectPath, CachedWirelessNetwork::Ptr> wifis;
> +            std::map<core::dbus::types::ObjectPath, org::freedesktop::NetworkManager::Device> wireless_devices;
> +        } cached;
> +
> +        struct
> +        {
> +            core::Signal<> wireless_network_scan_finished;
> +            core::Signal<com::ubuntu::location::connectivity::RadioCell::Ptr> connected_cell_added;
> +            core::Signal<com::ubuntu::location::connectivity::RadioCell::Ptr> connected_cell_removed;
> +            core::Signal<com::ubuntu::location::connectivity::WirelessNetwork::Ptr> wireless_network_added;
> +            core::Signal<com::ubuntu::location::connectivity::WirelessNetwork::Ptr> wireless_network_removed;
> +        } signals;
> +
> +        core::Property<com::ubuntu::location::connectivity::State> state;
> +    } d;
> +};
> +}
> +
> +#endif // OFONO_NM_CONNECTIVITY_MANAGER_H_
> 
> === added file 'src/location_service/com/ubuntu/location/connectivity/radio_cell.cpp'
> --- src/location_service/com/ubuntu/location/connectivity/radio_cell.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/radio_cell.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,118 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include <com/ubuntu/location/connectivity/radio_cell.h>
> +
> +namespace location = com::ubuntu::location;
> +
> +bool location::connectivity::operator==(const location::connectivity::RadioCell::Gsm& lhs,
> +                                        const location::connectivity::RadioCell::Gsm& rhs)
> +{
> +    return lhs.mobile_country_code == rhs.mobile_country_code &&
> +           lhs.mobile_network_code == rhs.mobile_network_code &&
> +           lhs.location_area_code == rhs.location_area_code &&
> +           lhs.id == rhs.id &&
> +           lhs.strength == rhs.strength;
> +}
> +
> +std::ostream& location::connectivity::operator<<(std::ostream& out, const location::connectivity::RadioCell::Gsm& gsm)
> +{
> +    out << "("
> +        << "mcc: " << gsm.mobile_country_code << ", "
> +        << "mnc: " << gsm.mobile_network_code << ", "
> +        << "lac: " << gsm.location_area_code << ", "
> +        << "id: " << gsm.id << ", "
> +        << "asu: " << gsm.strength << ")";
> +
> +    return out;
> +}
> +
> +bool location::connectivity::operator==(const location::connectivity::RadioCell::Umts& lhs, const location::connectivity::RadioCell::Umts& rhs)
> +{
> +    return lhs.mobile_country_code == rhs.mobile_country_code &&
> +            lhs.mobile_network_code == rhs.mobile_network_code &&
> +            lhs.location_area_code == rhs.location_area_code &&
> +            lhs.id == rhs.id &&
> +            lhs.strength == rhs.strength;
> +}
> +
> +std::ostream& location::connectivity::operator<<(std::ostream& out, const location::connectivity::RadioCell::Umts& umts)
> +{
> +    out << "("
> +        << "mcc: " << umts.mobile_country_code << ", "
> +        << "mnc: " << umts.mobile_network_code << ", "
> +        << "lac: " << umts.location_area_code << ", "
> +        << "id: " << umts.id << ", "
> +        << "asu: " << umts.strength << ")";
> +
> +    return out;
> +}
> +
> +bool location::connectivity::operator==(const location::connectivity::RadioCell::Lte& lhs,
> +                                        const location::connectivity::RadioCell::Lte& rhs)
> +{
> +    return lhs.mobile_country_code == rhs.mobile_country_code &&
> +            lhs.mobile_network_code == rhs.mobile_network_code &&
> +            lhs.tracking_area_code == rhs.tracking_area_code &&
> +            lhs.id == rhs.id &&
> +            lhs.physical_id == rhs.physical_id &&
> +            lhs.strength == rhs.strength;
> +}
> +
> +std::ostream& location::connectivity::operator<<(std::ostream& out, const location::connectivity::RadioCell::Lte& lte)
> +{
> +    out << "("
> +        << "mcc: " << lte.mobile_country_code << ", "
> +        << "mnc: " << lte.mobile_network_code << ", "
> +        << "lac: " << lte.tracking_area_code << ", "
> +        << "id: " << lte.id << ", "
> +        << "id: " << lte.physical_id << ", "
> +        << "asu: " << lte.strength << ")";
> +
> +    return out;
> +}
> +
> +bool location::connectivity::operator==(const location::connectivity::RadioCell& lhs,
> +                                        const location::connectivity::RadioCell& rhs)
> +{
> +    if (lhs.type() != rhs.type())
> +        return false;
> +
> +    switch(lhs.type())
> +    {
> +    case location::connectivity::RadioCell::Type::gsm: return lhs.gsm() == rhs.gsm();
> +    case location::connectivity::RadioCell::Type::umts: return lhs.umts() == rhs.umts();
> +    case location::connectivity::RadioCell::Type::lte: return lhs.lte() == rhs.lte();
> +    default: return true;
> +    }
> +
> +    return false;
> +}
> +
> +std::ostream& location::connectivity::operator<<(std::ostream& out, const location::connectivity::RadioCell& cell)
> +{
> +    switch (cell.type())
> +    {
> +    case location::connectivity::RadioCell::Type::gsm: out << "gsm" << cell.gsm(); break;
> +    case location::connectivity::RadioCell::Type::umts: out << "umts" << cell.umts(); break;
> +    case location::connectivity::RadioCell::Type::lte: out << "lte" << cell.lte(); break;
> +    case location::connectivity::RadioCell::Type::unknown: break;
> +    }
> +
> +    return out;
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/connectivity/wireless_network.cpp'
> --- src/location_service/com/ubuntu/location/connectivity/wireless_network.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/connectivity/wireless_network.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,47 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include <com/ubuntu/location/connectivity/wireless_network.h>
> +
> +#include <iostream>
> +
> +namespace location = com::ubuntu::location;
> +
> +std::ostream& location::connectivity::operator<<(std::ostream& out, location::connectivity::WirelessNetwork::Mode mode)
> +{
> +    switch (mode)
> +    {
> +    case location::connectivity::WirelessNetwork::Mode::unknown: out << "Mode::unknown"; break;
> +    case location::connectivity::WirelessNetwork::Mode::adhoc: out << "Mode::adhoc"; break;
> +    case location::connectivity::WirelessNetwork::Mode::infrastructure: out << "Mode::infrastructure"; break;
> +    }
> +
> +    return out;
> +}
> +
> +std::ostream& location::connectivity::operator<<(std::ostream& out, const location::connectivity::WirelessNetwork& wifi)
> +{
> +    return out << "("
> +               << "bssid: " << wifi.bssid().get() << ", "
> +               << "ssid: " << wifi.ssid().get() << ", "
> +               << "last seen: " << wifi.last_seen().get().time_since_epoch().count() << ", "
> +               << "mode: " << wifi.mode().get() << ", "
> +               << "frequency: " << wifi.frequency().get() << ", "
> +               << "strength: " << wifi.signal_strength().get()
> +               << ")";
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/criteria.cpp'
> --- src/location_service/com/ubuntu/location/criteria.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/criteria.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,99 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include <com/ubuntu/location/criteria.h>
> +
> +bool com::ubuntu::location::Criteria::satisfies(const com::ubuntu::location::Criteria& rhs) const
> +{
> +    bool result = false;
> +
> +    if (rhs.requires.position)
> +        result &= requires.position;
> +
> +    if (rhs.requires.altitude)
> +        result &= requires.altitude;
> +
> +    if (rhs.requires.heading)
> +        result &= requires.heading;
> +
> +    if (rhs.requires.velocity)
> +        result &= requires.velocity;
> +
> +    result &= accuracy.horizontal <= rhs.accuracy.horizontal;
> +
> +    if (rhs.accuracy.vertical)
> +        result &= accuracy.vertical && accuracy.vertical <= rhs.accuracy.vertical;
> +
> +    if (rhs.accuracy.heading)
> +        result &= accuracy.heading && accuracy.heading <= rhs.accuracy.heading;
> +
> +    if (rhs.accuracy.velocity)
> +        result &= accuracy.velocity && accuracy.velocity <= rhs.accuracy.velocity;
> +
> +    return result;
> +}
> +
> +com::ubuntu::location::Criteria com::ubuntu::location::operator+(
> +        const com::ubuntu::location::Criteria& lhs,
> +        const com::ubuntu::location::Criteria& rhs)
> +{
> +    Criteria result{lhs};
> +
> +    result.requires.position |= rhs.requires.position;
> +    result.requires.velocity |= rhs.requires.velocity;
> +    result.requires.heading |= rhs.requires.heading;
> +    result.requires.altitude |= rhs.requires.altitude;
> +
> +    if (rhs.accuracy.horizontal < result.accuracy.horizontal)
> +        result.accuracy.horizontal = rhs.accuracy.horizontal;
> +
> +    if (result.accuracy.vertical)
> +    {
> +        if (rhs.accuracy.vertical && rhs.accuracy.vertical < result.accuracy.vertical)
> +        {
> +            result.accuracy.vertical = rhs.accuracy.vertical;
> +        }
> +    } else
> +    {
> +        result.accuracy.vertical = rhs.accuracy.vertical;
> +    }
> +
> +    if (result.accuracy.velocity)
> +    {
> +        if (rhs.accuracy.velocity && rhs.accuracy.velocity < result.accuracy.velocity)
> +        {
> +            result.accuracy.velocity = rhs.accuracy.velocity;
> +        }
> +    } else
> +    {
> +        result.accuracy.velocity = rhs.accuracy.velocity;
> +    }
> +
> +    if (result.accuracy.heading)
> +    {
> +        if (rhs.accuracy.heading && rhs.accuracy.heading < result.accuracy.heading)
> +        {
> +            result.accuracy.heading = rhs.accuracy.heading;
> +        }
> +    } else
> +    {
> +        result.accuracy.heading = rhs.accuracy.heading;
> +    }
> +
> +    return result;
> +}
> 
> === modified file 'src/location_service/com/ubuntu/location/default_permission_manager.cpp'
> --- src/location_service/com/ubuntu/location/default_permission_manager.cpp	2013-05-28 14:41:06 +0000
> +++ src/location_service/com/ubuntu/location/default_permission_manager.cpp	2014-06-24 16:02:38 +0000
> @@ -15,7 +15,7 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/default_permission_manager.h"
> +#include <com/ubuntu/location/default_permission_manager.h>
>  
>  namespace cul = com::ubuntu::location;
>  
> 
> === modified file 'src/location_service/com/ubuntu/location/default_provider_selection_policy.cpp'
> --- src/location_service/com/ubuntu/location/default_provider_selection_policy.cpp	2013-06-10 11:10:00 +0000
> +++ src/location_service/com/ubuntu/location/default_provider_selection_policy.cpp	2014-06-24 16:02:38 +0000
> @@ -15,10 +15,30 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/default_provider_selection_policy.h"
> +#include <com/ubuntu/location/default_provider_selection_policy.h>
> +
> +#include <com/ubuntu/location/engine.h>
>  
>  namespace cul = com::ubuntu::location;
>  
> +namespace
> +{
> +struct NullProvider : public cul::Provider
> +{
> +    NullProvider() = default;
> +};
> +
> +std::shared_ptr<cul::Provider> null_provider_instance
> +{
> +    new NullProvider{}
> +};
> +}
> +
> +const cul::Provider::Ptr& cul::ProviderSelectionPolicy::null_provider()
> +{
> +    return null_provider_instance;
> +}
> +
>  cul::DefaultProviderSelectionPolicy::DefaultProviderSelectionPolicy()
>  {
>  }
> @@ -28,15 +48,15 @@
>  }
>  
>  cul::ProviderSelection 
> -cul::DefaultProviderSelectionPolicy::determine_provider_selection_from_set_for_criteria(
> +cul::DefaultProviderSelectionPolicy::determine_provider_selection_for_criteria(
>      const cul::Criteria& criteria,
> -    const std::set<cul::Provider::Ptr>& providers)
> +    const cul::ProviderEnumerator& enumerator)
>  {
>      ProviderSelection selection
>      {
> -        determine_position_updates_provider(criteria, providers),
> -        determine_heading_updates_provider(criteria, providers),
> -        determine_velocity_updates_provider(criteria, providers),
> +        determine_position_updates_provider(criteria, enumerator),
> +        determine_heading_updates_provider(criteria, enumerator),
> +        determine_velocity_updates_provider(criteria, enumerator)
>      };
>      
>      return selection;
> @@ -45,7 +65,7 @@
>  cul::Provider::Ptr 
>  cul::DefaultProviderSelectionPolicy::determine_position_updates_provider(
>      const cul::Criteria& criteria,
> -    const std::set<cul::Provider::Ptr>& providers)
> +    const cul::ProviderEnumerator& enumerator)
>  {
>      auto less = 
>              [](const Provider::Ptr& lhs, const Provider::Ptr& rhs)
> @@ -55,24 +75,22 @@
>              };
>  
>      std::set<
> -        Provider::Ptr, 
> +        Provider::Ptr,
>          std::function<bool(const Provider::Ptr&, const Provider::Ptr&)>> matching_providers(less);
>  
> -    std::for_each(
> -        providers.begin(), 
> -        providers.end(), 
> +    enumerator.for_each_provider(
>          [&](const Provider::Ptr& provider)
>          {
>              if (provider->matches_criteria(criteria))
>                  matching_providers.insert(provider);
>          });
>  
> -    return matching_providers.empty() ? Provider::Ptr {} : *matching_providers.begin();
> +    return matching_providers.empty() ? null_provider() : *matching_providers.begin();
>  }
>  
>  cul::Provider::Ptr cul::DefaultProviderSelectionPolicy::determine_heading_updates_provider(
>      const cul::Criteria& criteria,
> -    const std::set<cul::Provider::Ptr>& providers)
> +    const cul::ProviderEnumerator& enumerator)
>  {
>      auto less = 
>              [](const Provider::Ptr& lhs, const Provider::Ptr& rhs)
> @@ -84,21 +102,19 @@
>          Provider::Ptr, 
>          std::function<bool(const Provider::Ptr&, const Provider::Ptr&)>> matching_providers(less);
>  
> -    std::for_each(
> -        providers.begin(), 
> -        providers.end(), 
> +    enumerator.for_each_provider(
>          [&](const Provider::Ptr& provider)
>          {
>              if (provider->matches_criteria(criteria))
>                  matching_providers.insert(provider);
>          });
>  
> -    return matching_providers.empty() ? Provider::Ptr {} : *matching_providers.begin();
> +    return matching_providers.empty() ? null_provider() : *matching_providers.begin();
>  }
>  
>  cul::Provider::Ptr cul::DefaultProviderSelectionPolicy::determine_velocity_updates_provider(
>      const cul::Criteria& criteria,
> -    const std::set<cul::Provider::Ptr>& providers)
> +    const cul::ProviderEnumerator& enumerator)
>  {
>      auto less = 
>              [](const Provider::Ptr& lhs, const Provider::Ptr& rhs)
> @@ -110,15 +126,12 @@
>          Provider::Ptr, 
>          std::function<bool(const Provider::Ptr&, const Provider::Ptr&)>> matching_providers(less);
>  
> -    std::for_each(
> -        providers.begin(), 
> -        providers.end(), 
> +    enumerator.for_each_provider(
>          [&](const Provider::Ptr& provider)
>          {
>              if (provider->matches_criteria(criteria))
>                  matching_providers.insert(provider);
>          });
>  
> -    return matching_providers.empty() ? Provider::Ptr {} :
> -    *matching_providers.begin();
> +    return matching_providers.empty() ? null_provider() : *matching_providers.begin();
>  }
> 
> === modified file 'src/location_service/com/ubuntu/location/engine.cpp'
> --- src/location_service/com/ubuntu/location/engine.cpp	2013-06-10 11:10:00 +0000
> +++ src/location_service/com/ubuntu/location/engine.cpp	2014-06-24 16:02:38 +0000
> @@ -15,24 +15,53 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/engine.h"
> +#include <com/ubuntu/location/engine.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +#include <com/ubuntu/location/provider_selection_policy.h>
>  
>  #include <stdexcept>
>  
>  namespace cul = com::ubuntu::location;
>  
> -cul::Engine::Engine(const std::set<cul::Provider::Ptr>& initial_providers,
> -                    const cul::ProviderSelectionPolicy::Ptr& provider_selection_policy)
> -        : providers(initial_providers),
> -          provider_selection_policy(provider_selection_policy)
> +cul::Engine::Engine(const std::shared_ptr<cul::ProviderSelectionPolicy>& provider_selection_policy)
> +          : provider_selection_policy(provider_selection_policy)
>  {
>      if (!provider_selection_policy)
>          std::runtime_error("Cannot construct an engine given a null ProviderSelectionPolicy");
> +
> +    // Setup behavior in case of configuration changes.
> +    configuration.engine_state.changed().connect([this](const Engine::Status& status)
> +    {
> +        switch (status)
> +        {
> +        case Engine::Status::off:
> +            for_each_provider([](const Provider::Ptr& provider)
> +            {
> +                provider->state_controller()->stop_position_updates();
> +                provider->state_controller()->stop_heading_updates();
> +                provider->state_controller()->stop_velocity_updates();
> +            });
> +            break;
> +        default:
> +            break;
> +        }
> +    });
> +}
> +
> +cul::Engine::~Engine()
> +{
> +    for_each_provider([](const Provider::Ptr& provider)
> +    {
> +        provider->state_controller()->stop_position_updates();
> +        provider->state_controller()->stop_heading_updates();
> +        provider->state_controller()->stop_velocity_updates();
> +    });
>  }
>  
>  cul::ProviderSelection cul::Engine::determine_provider_selection_for_criteria(const cul::Criteria& criteria)
>  {
> -    return provider_selection_policy->determine_provider_selection_from_set_for_criteria(criteria, providers);
> +    return provider_selection_policy->determine_provider_selection_for_criteria(criteria, *this);
>  }
>  
>  bool cul::Engine::has_provider(const cul::Provider::Ptr& provider) noexcept
> @@ -45,10 +74,67 @@
>      if (!provider)
>          throw std::runtime_error("Cannot add null provider");
>  
> -    providers.insert(provider);
> +    // We wire up changes in the engine's configuration to the respective slots
> +    // of the provider.
> +    auto cp = updates.reference_location.changed().connect([provider](const cul::Update<cul::Position>& pos)
> +    {
> +        provider->on_reference_location_updated(pos);
> +    });
> +
> +    auto cv = updates.reference_velocity.changed().connect([provider](const cul::Update<cul::Velocity>& velocity)
> +    {
> +        provider->on_reference_velocity_updated(velocity);
> +    });
> +
> +    auto ch = updates.reference_heading.changed().connect([provider](const cul::Update<cul::Heading>& heading)
> +    {
> +        provider->on_reference_heading_updated(heading);
> +    });
> +
> +    auto cr = configuration.wifi_and_cell_id_reporting_state.changed().connect([provider](cul::WifiAndCellIdReportingState state)
> +    {
> +        provider->on_wifi_and_cell_reporting_state_changed(state);
> +    });
> +
> +    // And do the reverse: Satellite visibility updates are funneled via the engine's configuration.
> +    auto cs = provider->updates().svs.connect([this](const cul::Update<std::set<cul::SpaceVehicle>>& src)
> +    {
> +        updates.visible_space_vehicles.update([src](std::map<cul::SpaceVehicle::Key, cul::SpaceVehicle>& dest)
> +        {
> +            for(auto& sv : src.value)
> +            {
> +                dest[sv.key] = sv;
> +            }
> +
> +            return true;
> +        });
> +    });
> +
> +    // We are a bit dumb and just take any position update as new reference.
> +    // We should come up with a better heuristic here.
> +    auto cpr = provider->updates().position.connect([this](const cul::Update<cul::Position>& src)
> +    {
> +        updates.reference_location = src;
> +    });
> +
> +    std::lock_guard<std::mutex> lg(guard);
> +    providers.emplace(provider, std::move(ProviderConnections{cp, ch, cv, cr, cs, cpr}));
>  }
>  
>  void cul::Engine::remove_provider(const cul::Provider::Ptr& provider) noexcept
>  {
> -    providers.erase(provider);
> +    std::lock_guard<std::mutex> lg(guard);
> +
> +    auto it = providers.find(provider);
> +    if (it != providers.end())
> +    {
> +        providers.erase(it);
> +    }
> +}
> +
> +void cul::Engine::for_each_provider(const std::function<void(const Provider::Ptr&)>& enumerator) const noexcept
> +{
> +    std::lock_guard<std::mutex> lg(guard);
> +    for (const auto& provider : providers)
> +        enumerator(provider.first);
>  }
> 
> === modified file 'src/location_service/com/ubuntu/location/init_and_shutdown.cpp'
> --- src/location_service/com/ubuntu/location/init_and_shutdown.cpp	2013-05-29 09:21:16 +0000
> +++ src/location_service/com/ubuntu/location/init_and_shutdown.cpp	2014-06-24 16:02:38 +0000
> @@ -1,5 +1,5 @@
> -#include "com/ubuntu/location/init_and_shutdown.h"
> -#include "com/ubuntu/location/logging.h"
> +#include <com/ubuntu/location/init_and_shutdown.h>
> +#include <com/ubuntu/location/logging.h>
>  
>  #include <gflags/gflags.h>
>  
> @@ -25,11 +25,11 @@
>  
>  void cul::init(int* argc, char*** argv)
>  {
> -	static const bool remove_parsed_flags = true;
> -	google::ParseCommandLineFlags(argc, argv, remove_parsed_flags);
> +    static const bool remove_parsed_flags = true;
> +    google::ParseCommandLineFlags(argc, argv, remove_parsed_flags);
>  }
>  
>  void cul::shutdown()
>  {
> -	google::ShutDownCommandLineFlags();
> -}
> \ No newline at end of file
> +    google::ShutDownCommandLineFlags();
> +}
> 
> === modified file 'src/location_service/com/ubuntu/location/position.cpp'
> --- src/location_service/com/ubuntu/location/position.cpp	2013-05-28 14:41:06 +0000
> +++ src/location_service/com/ubuntu/location/position.cpp	2014-06-24 16:02:38 +0000
> @@ -15,112 +15,98 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/position.h"
> +#include <com/ubuntu/location/position.h>
>  
>  #include <bitset>
>  #include <ostream>
>  
>  namespace cul = com::ubuntu::location;
>  
> -cul::Position::Position() : fields{Flags("000"), wgs84::Latitude{}, wgs84::Longitude{}, wgs84::Altitude{}}
> -{
> -}
> -
> -cul::Position::Position(
> -    const cul::wgs84::Latitude& latitude,
> -    const cul::wgs84::Longitude& longitude)
> -        : fields{Flags("011"), latitude, longitude, wgs84::Altitude{}}
> -{
> -}          
> -
> -cul::Position::Position(
> -    const cul::wgs84::Latitude& latitude,
> -    const cul::wgs84::Longitude& longitude,
> -    const cul::wgs84::Altitude& altitude)
> -        : fields{Flags{"111"}, latitude, longitude, altitude}
> -{
> +cul::Position::Position(
> +        const cul::wgs84::Latitude& latitude,
> +        const cul::wgs84::Longitude& longitude)
> +    : latitude(latitude),
> +      longitude(longitude)
> +{
> +}
> +
> +cul::Position::Position(
> +        const cul::wgs84::Latitude& latitude,
> +        const cul::wgs84::Longitude& longitude,
> +        const cul::wgs84::Altitude& altitude)
> +    : latitude(latitude),
> +      longitude(longitude),
> +      altitude(altitude)
> +{
> +}
> +
> +cul::Position::Position(const cul::wgs84::Latitude& lat,
> +                        const cul::wgs84::Longitude& lon,
> +                        const cul::wgs84::Altitude& alt,
> +                        const cul::units::Quantity<cul::units::Length>& hor_acc)
> +    : cul::Position::Position(lat, lon, alt)
> +{
> +    accuracy.horizontal = hor_acc;
> +}
> +
> +cul::Position::Position(const cul::wgs84::Latitude& lat,
> +                        const cul::wgs84::Longitude& lon,
> +                        const cul::wgs84::Altitude& alt,
> +                        const cul::units::Quantity<cul::units::Length>& hor_acc,
> +                        const cul::units::Quantity<cul::units::Length>& ver_acc)
> +    : cul::Position::Position(lat, lon, alt, hor_acc)
> +{
> +    accuracy.vertical = ver_acc;
>  }
>  
>  bool cul::Position::operator==(const cul::Position& rhs) const
>  {
> -    return fields.latitude == rhs.fields.latitude && fields.longitude == rhs.fields.longitude && fields.altitude == rhs.fields.altitude;
> +    return latitude == rhs.latitude &&
> +            longitude == rhs.longitude &&
> +            altitude == rhs.altitude &&
> +            accuracy.horizontal == rhs.accuracy.horizontal &&
> +            accuracy.vertical == rhs.accuracy.vertical;
>  }
>  
>  bool cul::Position::operator!=(const cul::Position& rhs) const
>  {
> -    return !(fields.latitude == rhs.fields.latitude && fields.longitude == rhs.fields.longitude && fields.altitude == rhs.fields.altitude);
> -}
> -
> -const cul::Position::Flags& cul::Position::flags() const
> -{
> -    return fields.flags;
> -}
> -
> -bool cul::Position::has_latitude() const
> -{
> -    return fields.flags.test(latitude_flag);
> -}
> -
> -cul::Position& cul::Position::latitude(const cul::wgs84::Latitude& lat)
> -{
> -    fields.flags.set(latitude_flag);
> -    fields.latitude = lat;
> -    return *this;
> -}
> -
> -const cul::wgs84::Latitude& cul::Position::latitude() const
> -{
> -    return fields.latitude;
> -}
> -
> -bool cul::Position::has_longitude() const
> -{
> -    return fields.flags.test(longitude_flag);
> -}
> -
> -cul::Position& cul::Position::longitude(const cul::wgs84::Longitude& lon)
> -{
> -    fields.flags.set(longitude_flag);
> -    fields.longitude = lon;
> -    return *this;
> -}
> -
> -const cul::wgs84::Longitude& cul::Position::longitude() const
> -{
> -    return fields.longitude;
> -}
> -
> -bool cul::Position::has_altitude() const
> -{
> -    return fields.flags.test(altitude_flag);
> -}
> -
> -cul::Position& cul::Position::altitude(const cul::wgs84::Altitude& alt)
> -{
> -    fields.flags.set(altitude_flag);
> -    fields.altitude = alt;
> -    return *this;
> -}
> -
> -const cul::wgs84::Altitude& cul::Position::altitude() const
> -{
> -    return fields.altitude;
> +    return !(*this == rhs);
>  }
>  
>  std::ostream& cul::operator<<(std::ostream& out, const cul::Position& position)
>  {
> -    out << "Position(" << position.latitude() << ", " << position.longitude() << ", " << position.altitude() << ")";
> +    out << "Position("
> +        << "lat: " << position.latitude << ", "
> +        << "lon: " << position.longitude << ", ";
> +    out << "alt: ";
> +    if (position.altitude)
> +        out << *position.altitude;
> +    else
> +        out << "n/a";
> +    out << ", ";
> +    out << "hor.acc.: ";
> +    if (position.accuracy.horizontal)
> +        out << *position.accuracy.horizontal;
> +    else
> +        out << "n/a";
> +    out << ", ";
> +    out << "ver.acc.: ";
> +    if (position.accuracy.vertical)
> +        out << *position.accuracy.vertical;
> +    else
> +        out << "n/a";
> +    out << ")";
>      return out;
>  }
>  
>  cul::units::Quantity<cul::units::Length> cul::haversine_distance(const cul::Position& p1, const cul::Position& p2)
>  {
> -    static const units::Quantity<units::Length> radius_of_earth {6371 * units::kilo* units::Meters};
> -    auto dLat = p2.latitude() - p1.latitude();
> -    auto dLon = p2.longitude() - p1.longitude();
> +    static const units::Quantity<units::Length> radius_of_earth {6371 * units::kilo * units::Meters};
> +    auto dLat = p2.latitude - p1.latitude;
> +    auto dLon = p2.longitude - p1.longitude;
>      auto a =
>          std::pow(units::sin(dLat.value/2.), 2) +
> -        std::pow(units::sin(dLon.value/2.), 2) * units::cos(p1.latitude().value) * units::cos(p2.latitude().value);
> +        std::pow(units::sin(dLon.value/2.), 2) * units::cos(p1.latitude.value) * units::cos(p2.latitude.value);
>  
>      auto c = 2. * std::atan2(std::sqrt(a), std::sqrt(1.-a));
>      return radius_of_earth * c;
> 
> === modified file 'src/location_service/com/ubuntu/location/provider.cpp'
> --- src/location_service/com/ubuntu/location/provider.cpp	2013-06-10 11:10:00 +0000
> +++ src/location_service/com/ubuntu/location/provider.cpp	2014-06-24 16:02:38 +0000
> @@ -15,7 +15,7 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/provider.h"
> +#include <com/ubuntu/location/provider.h>
>  
>  #include <atomic>
>  #include <bitset>
> @@ -86,95 +86,27 @@
>      return velocity_updates_counter > 0;
>  }
>  
> -const cul::Provider::Controller::Cache<cul::Update<cul::Position>>& cul::Provider::Controller::cached_position_update() const
> -{
> -    return cached.position;
> -}
> -
> -const cul::Provider::Controller::Cache<cul::Update<cul::Heading>>& cul::Provider::Controller::cached_heading_update() const
> -{
> -    return cached.heading;
> -}
> -
> -const cul::Provider::Controller::Cache<cul::Update<cul::Velocity>>& cul::Provider::Controller::cached_velocity_update() const
> -{
> -    return cached.velocity;
> -}
> -
>  cul::Provider::Controller::Controller(cul::Provider& instance)
>      : instance(instance),
>        position_updates_counter(0),
>        heading_updates_counter(0),
> -      velocity_updates_counter(0),
> -      cached
> -      {
> -          Cache<Update<Position>>{},
> -          Cache<Update<Velocity>>{},
> -          Cache<Update<Heading>>{}
> -      }
> -{
> -    position_update_connection =
> -            instance.subscribe_to_position_updates(
> -                std::bind(&Controller::on_position_updated,
> -                          this,
> -                          std::placeholders::_1));
> -
> -    velocity_update_connection =
> -            instance.subscribe_to_velocity_updates(
> -                std::bind(&Controller::on_velocity_updated,
> -                          this,
> -                          std::placeholders::_1));
> -
> -    heading_update_connection =
> -            instance.subscribe_to_heading_updates(
> -                std::bind(&Controller::on_heading_updated,
> -                          this,
> -                          std::placeholders::_1));
> -}
> -
> -void cul::Provider::Controller::on_position_updated(const cul::Update<cul::Position>& position)
> -{
> -    cached.position.update(position);
> -}
> -
> -void cul::Provider::Controller::on_velocity_updated(const cul::Update<cul::Velocity>& velocity)
> -{
> -    cached.velocity.update(velocity);
> -}
> -
> -void cul::Provider::Controller::on_heading_updated(const cul::Update<cul::Heading>& heading)
> -{
> -    cached.heading.update(heading);
> +      velocity_updates_counter(0)
> +{
>  }
>  
>  const cul::Provider::Controller::Ptr& cul::Provider::state_controller() const
>  {
> -    return controller;
> -}
> -
> -cul::ChannelConnection cul::Provider::subscribe_to_position_updates(std::function<void(const cul::Update<cul::Position>&)> f)
> -{
> -    return position_updates_channel.connect(f);
> -}
> -
> -cul::ChannelConnection cul::Provider::subscribe_to_heading_updates(std::function<void(const cul::Update<cul::Heading>&)> f)
> -{
> -    return heading_updates_channel.connect(f);
> -}
> -
> -cul::ChannelConnection cul::Provider::subscribe_to_velocity_updates(std::function<void(const cul::Update<cul::Velocity>&)> f)
> -{
> -    return velocity_updates_channel.connect(f);
> -}
> -
> -bool cul::Provider::supports(const cul::Provider::Feature& f) const
> -{
> -    return feature_flags.test(static_cast<std::size_t>(f));
> -}
> -
> -bool cul::Provider::requires(const cul::Provider::Requirement& r) const
> -{
> -    return requirement_flags.test(static_cast<std::size_t>(r));
> +    return d.controller;
> +}
> +
> +bool cul::Provider::supports(const cul::Provider::Features& f) const
> +{
> +    return (d.features & f) != Features::none;
> +}
> +
> +bool cul::Provider::requires(const cul::Provider::Requirements& r) const
> +{
> +    return (d.requirements & r) != Requirements::none;
>  }
>  
>  bool cul::Provider::matches_criteria(const cul::Criteria&)
> @@ -182,28 +114,39 @@
>      return false;
>  }
>  
> +const cul::Provider::Updates& cul::Provider::updates() const
> +{
> +    return d.updates;
> +}
> +
>  cul::Provider::Provider(
> -    const cul::Provider::FeatureFlags& feature_flags,
> -    const cul::Provider::RequirementFlags& requirement_flags)
> -    : feature_flags(feature_flags),
> -      requirement_flags(requirement_flags),
> -      controller(new Controller(*this))
> -{
> -}
> -
> -void cul::Provider::deliver_position_updates(const cul::Update<cul::Position>& update)
> -{
> -    position_updates_channel(update);
> -}
> -
> -void cul::Provider::deliver_heading_updates(const cul::Update<cul::Heading>& update)
> -{
> -    heading_updates_channel(update);
> -}
> -
> -void cul::Provider::deliver_velocity_updates(const cul::Update<cul::Velocity>& update)
> -{
> -    velocity_updates_channel(update);
> +    const cul::Provider::Features& features,
> +    const cul::Provider::Requirements& requirements)
> +{
> +    d.features = features;
> +    d.requirements = requirements;
> +    d.controller = std::shared_ptr<Provider::Controller>(new Provider::Controller(*this));
> +}
> +
> +cul::Provider::Updates& cul::Provider::mutable_updates()
> +{
> +    return d.updates;
> +}
> +
> +void cul::Provider::on_wifi_and_cell_reporting_state_changed(cul::WifiAndCellIdReportingState)
> +{
> +}
> +
> +void cul::Provider::on_reference_location_updated(const cul::Update<cul::Position>&)
> +{
> +}
> +
> +void cul::Provider::on_reference_velocity_updated(const cul::Update<cul::Velocity>&)
> +{
> +}
> +
> +void cul::Provider::on_reference_heading_updated(const cul::Update<cul::Heading>&)
> +{
>  }
>  
>  void cul::Provider::start_position_updates() {}
> @@ -212,3 +155,23 @@
>  void cul::Provider::stop_heading_updates() {}
>  void cul::Provider::start_velocity_updates() {}
>  void cul::Provider::stop_velocity_updates() {}
> +
> +cul::Provider::Features cul::operator|(cul::Provider::Features lhs, cul::Provider::Features rhs)
> +{
> +    return static_cast<cul::Provider::Features>(static_cast<unsigned int>(lhs) | static_cast<unsigned int>(rhs));
> +}
> +
> +cul::Provider::Features cul::operator&(cul::Provider::Features lhs, cul::Provider::Features rhs)
> +{
> +    return static_cast<cul::Provider::Features>(static_cast<unsigned int>(lhs) & static_cast<unsigned int>(rhs));
> +}
> +
> +cul::Provider::Requirements cul::operator|(cul::Provider::Requirements lhs, cul::Provider::Requirements rhs)
> +{
> +    return static_cast<cul::Provider::Requirements>(static_cast<unsigned int>(lhs) | static_cast<unsigned int>(rhs));
> +}
> +
> +cul::Provider::Requirements cul::operator&(cul::Provider::Requirements lhs, cul::Provider::Requirements rhs)
> +{
> +    return static_cast<cul::Provider::Requirements>(static_cast<unsigned int>(lhs) & static_cast<unsigned int>(rhs));
> +}
> 
> === modified file 'src/location_service/com/ubuntu/location/provider_factory.cpp'
> --- src/location_service/com/ubuntu/location/provider_factory.cpp	2013-05-28 14:41:06 +0000
> +++ src/location_service/com/ubuntu/location/provider_factory.cpp	2014-06-24 16:02:38 +0000
> @@ -15,8 +15,8 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/provider_factory.h"
> -#include "com/ubuntu/location/provider.h"
> +#include <com/ubuntu/location/provider_factory.h>
> +#include <com/ubuntu/location/provider.h>
>  
>  #include <functional>
>  #include <map>
> 
> === modified file 'src/location_service/com/ubuntu/location/providers/dummy/provider.cpp'
> --- src/location_service/com/ubuntu/location/providers/dummy/provider.cpp	2014-02-10 08:31:32 +0000
> +++ src/location_service/com/ubuntu/location/providers/dummy/provider.cpp	2014-06-24 16:02:38 +0000
> @@ -57,28 +57,47 @@
>  
>      provider_config.update_period = std::chrono::milliseconds
>      {
> -            config.get(dummy::Configuration::key_update_period(), 500)
> -    };
> -    provider_config.reference_position.latitude(wgs84::Latitude
> -    {
> -            config.get(dummy::Configuration::key_reference_position_lat(), 51.) * units::Degrees
> -    });
> -    provider_config.reference_position.longitude(wgs84::Longitude
> -    {
> -            config.get(dummy::Configuration::key_reference_position_lon(), 7.) * units::Degrees
> -    });
> +        config.get(dummy::Configuration::Keys::update_period, 500)
> +    };
> +    provider_config.reference_position.latitude = location::wgs84::Latitude
> +    {
> +        config.get(dummy::Configuration::Keys::reference_position_lat, 51.) * location::units::Degrees
> +    };
> +    provider_config.reference_position.longitude = location::wgs84::Longitude
> +    {
> +        config.get(dummy::Configuration::Keys::reference_position_lon, 7.) * location::units::Degrees
> +    };
> +
> +    if (config.count(dummy::Configuration::Keys::reference_position_alt) > 0)
> +        provider_config.reference_position.altitude = location::wgs84::Altitude
> +        {
> +            config.get(dummy::Configuration::Keys::reference_position_alt, 0.) * location::units::Meters
> +        };
> +
> +    if (config.count(dummy::Configuration::Keys::reference_horizontal_accuracy) > 0)
> +        provider_config.reference_position.accuracy.horizontal =
> +            config.get(dummy::Configuration::Keys::reference_horizontal_accuracy, 0.) * location::units::Meters;
> +
> +    if (config.count(dummy::Configuration::Keys::reference_vertical_accuracy) > 0)
> +        provider_config.reference_position.accuracy.vertical =
> +            config.get(dummy::Configuration::Keys::reference_vertical_accuracy, 0.) * location::units::Meters;
> +
> +    provider_config.reference_velocity = location::Velocity
> +    {
> +        config.get(dummy::Configuration::Keys::reference_velocity, 9.) * location::units::MetersPerSecond
> +    };
> +    provider_config.reference_heading = location::Heading
> +    {
> +        config.get(dummy::Configuration::Keys::reference_heading, 127.) * location::units::Degrees
> +    };
>  
>      return location::Provider::Ptr{new dummy::Provider{provider_config}};
>  }
>  
> -namespace
> -{
> -location::Provider::FeatureFlags features{"111"};
> -location::Provider::RequirementFlags requirements{"0000"};
> -}
> -
>  dummy::Provider::Provider(const dummy::Configuration& config)
> -    : location::Provider(features, requirements),
> +    : location::Provider(
> +          location::Provider::Features::position | location::Provider::Features::velocity | location::Provider::Features::heading,
> +          location::Provider::Requirements::none),
>        d(new Private{config})
>  {
>  }
> @@ -86,6 +105,9 @@
>  dummy::Provider::~Provider() noexcept
>  {
>      stop_position_updates();
> +
> +    if (d->worker.joinable())
> +        d->worker.join();
>  }
>  
>  bool dummy::Provider::matches_criteria(const location::Criteria&)
> @@ -103,26 +125,41 @@
>      d->worker = std::move(std::thread([this]()
>      {
>          d->state.store(Private::State::started);
> -        VLOG(1) << "dummy::Provider::start_position_updates: started";
> +        VLOG(1) << __PRETTY_FUNCTION__ << ": started";
>  
> -        location::Update<location::Position> update
> +        location::Update<location::Position> position_update
>          {
>              d->configuration.reference_position,
>              location::Clock::now()
>          };
>  
> -        timespec ts {0, d->configuration.update_period.count() * 1000 * 1000};
> +        location::Update<location::Heading> heading_update
> +        {
> +            d->configuration.reference_heading,
> +            location::Clock::now()
> +        };
> +
> +        location::Update<location::Velocity> velocity_update
> +        {
> +            d->configuration.reference_velocity,
> +            location::Clock::now()
> +        };
>  
>          while (!d->stop_requested)
>          {
> -            update.when = location::Clock::now();
> -            deliver_position_updates(update);
> -            ::nanosleep(&ts, nullptr);
> +            position_update.when = location::Clock::now();
> +            heading_update.when = location::Clock::now();
> +            velocity_update.when = location::Clock::now();
> +
> +            mutable_updates().position(position_update);
> +            mutable_updates().heading(heading_update);
> +            mutable_updates().velocity(velocity_update);
> +
> +            std::this_thread::sleep_for(d->configuration.update_period);
>          }
> +
> +        d->state.store(Private::State::stopped);
>      }));
> -
> -    d->state.store(Private::State::stopped);
> -    VLOG(1) << "dummy::Provider::start_position_updates: stopped";
>  }
>  
>  void dummy::Provider::stop_position_updates()
> @@ -131,11 +168,11 @@
>          return;
>  
>      d->state.store(Private::State::stopping);
> -    VLOG(1) << "dummy::Provider::stop_position_updates: stopping";
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": stopping";
> +
> +    d->stop_requested = true;
> +
>      if (d->worker.joinable())
> -    {
> -        d->stop_requested = true;
>          d->worker.join();
> -    }
>  }
>  
> 
> === modified file 'src/location_service/com/ubuntu/location/providers/dummy/provider.h'
> --- src/location_service/com/ubuntu/location/providers/dummy/provider.h	2014-02-09 18:52:25 +0000
> +++ src/location_service/com/ubuntu/location/providers/dummy/provider.h	2014-06-24 16:02:38 +0000
> @@ -31,31 +31,76 @@
>  {
>  namespace dummy
>  {
> -
> +// Summarizes the configuration options known to the dummy provider.
>  struct Configuration
>  {
> -    inline static const char* key_update_period()
> -    {
> -        return "dummy::UpdatePeriodInMs";
> -    }
> -
> -    inline static const char* key_reference_position_lat()
> -    {
> -        return "ReferenceLocationLat";
> -    }
> -
> -    inline static const char* key_reference_position_lon()
> -    {
> -        return "ReferenceLocationLon";
> -    }
> -
> +    // All configuration keys known to the dummy provider.
> +    struct Keys
> +    {
> +        static constexpr const char* update_period
> +        {
> +            "UpdatePeriodInMs"
> +        };
> +        static constexpr const char* reference_position_lat
> +        {
> +            "ReferenceLocationLat"
> +        };
> +        static constexpr const char* reference_position_lon
> +        {
> +            "ReferenceLocationLon"
> +        };
> +        static constexpr const char* reference_position_alt
> +        {
> +            "ReferenceLocationAlt"
> +        };
> +        static constexpr const char* reference_horizontal_accuracy
> +        {
> +            "ReferenceHorizontalAccuracy"
> +        };
> +        static constexpr const char* reference_vertical_accuracy
> +        {
> +            "ReferenceVerticalAccuracy"
> +        };
> +        static constexpr const char* reference_velocity
> +        {
> +            "ReferenceVelocity"
> +        };
> +        static constexpr const char* reference_heading
> +        {
> +            "ReferenceHeading"
> +        };
> +    };
> +
> +    // Updates are delivered every update_period milliseconds.
>      std::chrono::milliseconds update_period{500};
>  
> +    // The reference position that is delivered in every upate cycle.
>      Position reference_position
>      {
> -        wgs84::Latitude{9. * units::Degrees},
> -        wgs84::Longitude{53. * units::Degrees},
> -        wgs84::Altitude{-2. * units::Meters}
> +        wgs84::Latitude
> +        {
> +            9. * units::Degrees
> +        },
> +        wgs84::Longitude
> +        {
> +            53. * units::Degrees
> +        },
> +        wgs84::Altitude
> +        {
> +            -2. * units::Meters
> +        }
> +    };
> +
> +    // The reference velocity that is delivered in every update cycle.
> +    Velocity reference_velocity
> +    {
> +        9 * units::MetersPerSecond
> +    };
> +
> +    // The reference heading that is delivered in every update cycle.
> +    Heading reference_heading
> +    {
> +        127 * units::Degrees
>      };
>  };
>  
> @@ -64,17 +109,22 @@
>    public:
>      // For integration with the Provider factory.
>      static std::string class_name();
> +    // Instantiates a new provider instance, populating the configuration object
> +    // from the provided property bundle. Please see dummy::Configuration::Keys
> +    // for the list of known options.
>      static Provider::Ptr create_instance(const ProviderFactory::Configuration&);
>  
> +    // Creates a new provider instance from the given configuration.
>      Provider(const Configuration& config = Configuration{});
> -    Provider(const Provider&) = delete;
> -    Provider& operator=(const Provider&) = delete;
> +    // Cleans up all resources and stops the updates.
>      ~Provider() noexcept;
>  
> -    // From Provider
> +    // Always returns true.
>      bool matches_criteria(const Criteria&);
>  
> +    // Starts up the updater thread and delivers position updates
>      void start_position_updates();
> +    // Stops the updater thread.
>      void stop_position_updates();
>  
>    private:
> 
> === modified file 'src/location_service/com/ubuntu/location/providers/geoclue/CMakeLists.txt'
> --- src/location_service/com/ubuntu/location/providers/geoclue/CMakeLists.txt	2013-05-28 14:20:45 +0000
> +++ src/location_service/com/ubuntu/location/providers/geoclue/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -21,4 +21,4 @@
>      -DCOM_UBUNTU_LOCATION_SERVICE_PROVIDERS_GEOCLUE ${ENABLED_PROVIDER_TARGETS_DEFINITIONS}
>      PARENT_SCOPE
>    )
> -endif (LOCATION_SERVICE_ENABLE_GEOCLUE_PROVIDER)
> \ No newline at end of file
> +endif (LOCATION_SERVICE_ENABLE_GEOCLUE_PROVIDER)
> 
> === modified file 'src/location_service/com/ubuntu/location/providers/geoclue/provider.cpp'
> --- src/location_service/com/ubuntu/location/providers/geoclue/provider.cpp	2014-01-31 11:08:33 +0000
> +++ src/location_service/com/ubuntu/location/providers/geoclue/provider.cpp	2014-06-24 16:02:38 +0000
> @@ -15,8 +15,12 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/providers/geoclue/provider.h"
> -#include "com/ubuntu/location/providers/geoclue/geoclue.h"
> +#include <com/ubuntu/location/providers/geoclue/provider.h>
> +
> +#include <com/ubuntu/location/providers/geoclue/geoclue.h>
> +
> +#include <core/dbus/object.h>
> +#include <core/dbus/signal.h>
>  
>  #include "core/dbus/object.h"
>  #include "core/dbus/signal.h"
> @@ -39,6 +43,16 @@
>  
>  struct culpg::Provider::Private
>  {
> +    typedef dbus::Signal<
> +        org::freedesktop::Geoclue::Position::Signals::PositionChanged,
> +        org::freedesktop::Geoclue::Position::Signals::PositionChanged::ArgumentType
> +    > PositionChanged;
> +
> +    typedef dbus::Signal<
> +        org::freedesktop::Geoclue::Velocity::Signals::VelocityChanged,
> +        org::freedesktop::Geoclue::Velocity::Signals::VelocityChanged::ArgumentType
> +    > VelocityChanged;
> +
>      Private(const culpg::Provider::Configuration& config) 
>              : bus(the_session_bus()),
>                service(dbus::Service::use_service(bus, config.name)),
> @@ -64,27 +78,10 @@
>      dbus::Bus::Ptr bus;
>      dbus::Service::Ptr service;
>      dbus::Object::Ptr object;
> -    dbus::Signal<
> -        org::freedesktop::Geoclue::Position::Signals::PositionChanged, 
> -        org::freedesktop::Geoclue::Position::Signals::PositionChanged::ArgumentType
> -        >::Ptr signal_position_changed;
> -    dbus::Signal<
> -        org::freedesktop::Geoclue::Velocity::Signals::VelocityChanged, 
> -        org::freedesktop::Geoclue::Velocity::Signals::VelocityChanged::ArgumentType
> -        >::Ptr signal_velocity_changed;
> -
> -    typedef typename dbus::Signal<
> -        org::freedesktop::Geoclue::Position::Signals::PositionChanged,
> -        org::freedesktop::Geoclue::Position::Signals::PositionChanged::ArgumentType
> -    >::SubscriptionToken SignalPositionChangedSubscription;
> -
> -    typedef typename dbus::Signal<
> -        org::freedesktop::Geoclue::Velocity::Signals::VelocityChanged,
> -        org::freedesktop::Geoclue::Velocity::Signals::VelocityChanged::ArgumentType
> -    >::SubscriptionToken SignalVelocityChangedSubscription;
> -
> -    SignalPositionChangedSubscription position_updates_connection;
> -    SignalVelocityChangedSubscription velocity_updates_connection;
> +    PositionChanged::Ptr signal_position_changed;
> +    VelocityChanged::Ptr signal_velocity_changed;
> +    PositionChanged::SubscriptionToken position_updates_connection;
> +    VelocityChanged::SubscriptionToken velocity_updates_connection;
>  
>      std::thread worker;
>  };
> @@ -97,18 +94,6 @@
>      return cul::Provider::Ptr{new culpg::Provider{pConfig}};
>  }
>  
> -const cul::Provider::FeatureFlags& culpg::Provider::default_feature_flags()
> -{
> -    static const cul::Provider::FeatureFlags flags{"001"};
> -    return flags;
> -}
> -
> -const cul::Provider::RequirementFlags& culpg::Provider::default_requirement_flags()
> -{
> -    static const cul::Provider::RequirementFlags flags{"1010"};
> -    return flags;
> -}
> -
>  culpg::Provider::Provider(const culpg::Provider::Configuration& config) 
>          : com::ubuntu::location::Provider(config.features, config.requirements),
>            d(new Private(config))
> @@ -118,19 +103,19 @@
>                  [this](const org::freedesktop::Geoclue::Position::Signals::PositionChanged::ArgumentType& arg)
>                  {
>                      org::freedesktop::Geoclue::Position::FieldFlags flags{static_cast<unsigned long>(std::get<0>(arg))};
> -                    cul::Update<cul::Position> update
> +                    cul::Position pos
>                      {
> -                        {
> -                            flags.test(org::freedesktop::Geoclue::Position::Field::latitude) ? 
> -                                    cul::wgs84::Latitude{std::get<2>(arg)* cul::units::Degrees} : cul::wgs84::Latitude{},
> -                            flags.test(org::freedesktop::Geoclue::Position::Field::longitude) ? 
> -                                    cul::wgs84::Longitude{std::get<3>(arg)* cul::units::Degrees} : cul::wgs84::Longitude{},
> -                            flags.test(org::freedesktop::Geoclue::Position::Field::altitude) ? 
> -                                    cul::wgs84::Altitude{std::get<4>(arg)* cul::units::Meters} : cul::wgs84::Altitude{}
> -                        },
> -                        cul::Clock::now()
> +                        flags.test(org::freedesktop::Geoclue::Position::Field::latitude) ?
> +                                cul::wgs84::Latitude{std::get<2>(arg)* cul::units::Degrees} : cul::wgs84::Latitude{},
> +                        flags.test(org::freedesktop::Geoclue::Position::Field::longitude) ?
> +                                cul::wgs84::Longitude{std::get<3>(arg)* cul::units::Degrees} : cul::wgs84::Longitude{}
>                      };
> -                    this->deliver_position_updates(update);
> +
> +                    if (flags.test(org::freedesktop::Geoclue::Position::Field::altitude))
> +                        pos.altitude = cul::wgs84::Altitude{std::get<4>(arg)* cul::units::Meters};
> +
> +                    cul::Update<cul::Position> update(pos);
> +                    this->mutable_updates().position(update);
>                  });
>  
>      d->velocity_updates_connection = 
> @@ -147,7 +132,7 @@
>                              std::get<2>(arg) * cul::units::MetersPerSecond,
>                              cul::Clock::now()
>                          };
> -                        this->deliver_velocity_updates(update);
> +                        this->mutable_updates().velocity(update);
>                      }
>  
>                      if (flags.test(org::freedesktop::Geoclue::Velocity::Field::direction))
> @@ -158,7 +143,7 @@
>                              cul::Clock::now()
>                          };
>                              
> -                        this->deliver_heading_updates(update);
> +                        this->mutable_updates().heading(update);
>                      }
>                  });
>  
> 
> === modified file 'src/location_service/com/ubuntu/location/providers/gps/CMakeLists.txt'
> --- src/location_service/com/ubuntu/location/providers/gps/CMakeLists.txt	2013-08-13 07:01:25 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/CMakeLists.txt	2014-06-24 16:02:38 +0000
> @@ -13,7 +13,17 @@
>    if (UBUNTU_HARDWARE_GPS_H)
>      message(STATUS "Enabling GPS location provider")
>  
> -    add_library(gps provider.cpp)
> +    add_library(
> +        gps
> +
> +        android_hardware_abstraction_layer.h
> +        android_hardware_abstraction_layer.cpp
> +
> +        hardware_abstraction_layer.h
> +        # hardware_abstraction_layer.cpp
> +
> +        provider.h
> +        provider.cpp)
>  
>      target_link_libraries(gps ubuntu_platform_hardware_api.so)
>    
> @@ -28,4 +38,4 @@
>        PARENT_SCOPE
>      )
>    endif (UBUNTU_HARDWARE_GPS_H)
> -endif (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
> \ No newline at end of file
> +endif (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
> 
> === added file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp'
> --- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,631 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include "android_hardware_abstraction_layer.h"
> +
> +#include "net_cpp_gps_xtra_downloader.h"
> +#include "null_gps_xtra_downloader.h"
> +
> +#include <com/ubuntu/location/clock.h>
> +#include <com/ubuntu/location/configuration.h>
> +#include <com/ubuntu/location/logging.h>
> +
> +#include <com/ubuntu/location/connectivity/manager.h>
> +
> +#include <ubuntu/hardware/gps.h>
> +
> +#include <boost/property_tree/ini_parser.hpp>
> +
> +#include <random>
> +
> +namespace gps = com::ubuntu::location::providers::gps;
> +namespace android = com::ubuntu::location::providers::gps::android;
> +
> +namespace location = com::ubuntu::location;
> +
> +namespace
> +{
> +std::shared_ptr<android::GpsXtraDownloader> create_xtra_downloader()
> +{
> +#if defined(COM_UBUNTU_LOCATION_SERVICE_HAVE_NET_CPP)
> +    return std::make_shared<android::NetCppGpsXtraDownloader>();
> +#else
> +    return std::make_shared<android::NullGpsXtraDownloader>();
> +#endif // COM_UBUNTU_LOCATION_SERVICE_HAVE_NET_CPP
> +}
> +}
> +
> +/** @brief Reads a configuration from a gps.conf file in INI format. */
> +android::GpsXtraDownloader::Configuration android::GpsXtraDownloader::Configuration::from_gps_conf_ini_file(std::istream& in)
> +{
> +    android::GpsXtraDownloader::Configuration result;
> +
> +    location::Configuration config;
> +    boost::property_tree::read_ini(in, config);
> +
> +    if (config.count("XTRA_SERVER_1") > 0)
> +        result.xtra_hosts.push_back(config.get<std::string>("XTRA_SERVER_1"));
> +    if (config.count("XTRA_SERVER_2") > 0)
> +        result.xtra_hosts.push_back(config.get<std::string>("XTRA_SERVER_2"));
> +    if (config.count("XTRA_SERVER_3") > 0)
> +        result.xtra_hosts.push_back(config.get<std::string>("XTRA_SERVER_3"));
> +
> +    result.timeout = std::chrono::milliseconds{1500};
> +
> +    return result;
> +}
> +
> +android::HardwareAbstractionLayer::SuplAssistant::SuplAssistant(android::HardwareAbstractionLayer& hal) : impl(hal)
> +{
> +}
> +
> +const core::Property<gps::HardwareAbstractionLayer::SuplAssistant::Status>& android::HardwareAbstractionLayer::SuplAssistant::status() const
> +{
> +    return impl.status;
> +}
> +
> +core::Property<gps::HardwareAbstractionLayer::SuplAssistant::Status>& android::HardwareAbstractionLayer::SuplAssistant::status()
> +{
> +    return impl.status;
> +}
> +
> +const core::Property<gps::HardwareAbstractionLayer::SuplAssistant::IpV4Address>& android::HardwareAbstractionLayer::SuplAssistant::server_ip() const
> +{
> +    return impl.server_ip;
> +}
> +
> +core::Property<gps::HardwareAbstractionLayer::SuplAssistant::IpV4Address>& android::HardwareAbstractionLayer::SuplAssistant::server_ip()
> +{
> +    return impl.server_ip;
> +}
> +
> +void android::HardwareAbstractionLayer::SuplAssistant::set_server(const std::string& host_name, std::uint16_t port)
> +{
> +    // TODO(tvoss): Reenable this once the platform api HAL changes land.
> +    u_hardware_gps_agps_set_server_for_type(
> +                impl.hal.impl.gps_handle,
> +                U_HARDWARE_GPS_AGPS_TYPE_SUPL,
> +                host_name.c_str(),
> +                port);
> +}
> +
> +void android::HardwareAbstractionLayer::SuplAssistant::notify_data_connection_open_via_apn(const std::string& name)
> +{
> +    // TODO(tvoss): Reenable this once the platform api HAL changes land.
> +    u_hardware_gps_agps_notify_connection_is_open(
> +                impl.hal.impl.gps_handle,
> +                name.c_str());
> +}
> +
> +void android::HardwareAbstractionLayer::SuplAssistant::notify_data_connection_closed()
> +{
> +    // TODO(tvoss): Reenable this once the platform api HAL changes land.
> +    u_hardware_gps_agps_notify_connection_is_closed(
> +                impl.hal.impl.gps_handle);
> +}
> +
> +void android::HardwareAbstractionLayer::SuplAssistant::notify_data_connection_not_available()
> +{
> +    // TODO(tvoss): Reenable this once the platform api HAL changes land.
> +    u_hardware_gps_agps_notify_connection_not_available(
> +                impl.hal.impl.gps_handle);
> +}
> +
> +android::HardwareAbstractionLayer::SuplAssistant::Impl::Impl(android::HardwareAbstractionLayer& hal) : hal(hal)
> +{
> +}
> +
> +void android::HardwareAbstractionLayer::on_nmea_update(int64_t timestamp, const char *nmea, int length, void *context)
> +{
> +    VLOG(20) << __PRETTY_FUNCTION__ << ": "
> +             << "timestamp=" << timestamp << " "
> +             << "nmea=" << nmea << " "
> +             << "length=" << length << " "
> +             << "context=" << context;
> +}
> +
> +void android::HardwareAbstractionLayer::on_xtra_download_request(void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": "
> +            << "context=" << context;
> +
> +    auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +
> +    auto xtra_gps_data = thiz->impl.gps_xtra_downloader->download_xtra_data(thiz->impl.gps_xtra_configuration);
> +    if (not xtra_gps_data.empty())
> +        u_hardware_gps_inject_xtra_data(thiz->impl.gps_handle, &xtra_gps_data.front(), xtra_gps_data.size());
> +}
> +
> +void android::HardwareAbstractionLayer::on_gps_ni_notify(UHardwareGpsNiNotification* notification, void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": "
> +            << "notification=" << notification << " "
> +            << "context=" << context;
> +}
> +
> +void android::HardwareAbstractionLayer::on_ril_request_set_id(uint32_t flags, void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": "
> +            << "flags=" << flags << " "
> +            << "context=" << context;
> +}
> +
> +void android::HardwareAbstractionLayer::on_ril_request_reference_location(uint32_t flags, void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": "
> +            << "flags=" << flags << " "
> +            << "context=" << context;
> +}
> +
> +void android::HardwareAbstractionLayer::on_location_update(UHardwareGpsLocation* location, void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__;
> +
> +    auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +
> +    if (location->flags & U_HARDWARE_GPS_LOCATION_HAS_LAT_LONG)
> +    {
> +        location::Position pos
> +        {
> +            location::wgs84::Latitude{location->latitude * location::units::Degrees},
> +            location::wgs84::Longitude{location->longitude * location::units::Degrees}
> +        };
> +
> +        if (location->flags & U_HARDWARE_GPS_LOCATION_HAS_ACCURACY)
> +            pos.accuracy.horizontal = location->accuracy * location::units::Meters;
> +
> +        if(location->flags & U_HARDWARE_GPS_LOCATION_HAS_ALTITUDE)
> +            pos.altitude = location::wgs84::Altitude{location->altitude * location::units::Meters};
> +
> +        // The Android HAL does not provide us with accuracy information for
> +        // altitude measurements. We just leave out that field.
> +
> +        thiz->position_updates()(pos);
> +
> +        VLOG(1) << pos;
> +    }
> +
> +    if (location->flags & U_HARDWARE_GPS_LOCATION_HAS_SPEED)
> +    {
> +        location::Velocity v{location->speed * location::units::MetersPerSecond};
> +        thiz->velocity_updates()(v);
> +        VLOG(1) << v;
> +    }
> +
> +    if (location->flags & U_HARDWARE_GPS_LOCATION_HAS_BEARING)
> +    {
> +        location::Heading h{location->bearing * location::units::Degrees};
> +        thiz->heading_updates()(h);
> +        VLOG(1) << h;
> +    }
> +}
> +
> +void android::HardwareAbstractionLayer::on_status_update(uint16_t status, void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": status=" << status << ", context=" << context;
> +    auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +    thiz->chipset_status() = static_cast<gps::ChipsetStatus>(status);
> +}
> +
> +void android::HardwareAbstractionLayer::on_sv_status_update(UHardwareGpsSvStatus* sv_info, void* context)
> +{
> +    VLOG(20) << __PRETTY_FUNCTION__ << ": "
> +             << "count: " << sv_info->num_svs << " "
> +             << "a: " << sv_info->almanac_mask << " "
> +             << "e: " << sv_info->ephemeris_mask << " "
> +             << "u: " << sv_info->used_in_fix_mask << " ";
> +
> +    auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +
> +    std::set<location::SpaceVehicle> svs;
> +
> +    for (int i = 0; i < sv_info->num_svs; i++)
> +    {
> +        location::SpaceVehicle sv;
> +
> +        // PRN is in the range of [1, 32], adjusting it to make sure we
> +        // can use it for bitfield flag testing operations.
> +        int prn = sv_info->sv_list[i].prn - 1;
> +        if (prn < 0)
> +            continue;
> +
> +        auto shift = (1 << prn);
> +
> +        sv.key.type = location::SpaceVehicle::Type::gps;
> +        sv.key.id = sv_info->sv_list[i].prn;
> +        sv.snr = sv_info->sv_list[i].snr;
> +        sv.has_almanac_data = sv_info->almanac_mask & shift;
> +        sv.has_ephimeris_data = sv_info->ephemeris_mask & shift;
> +        sv.used_in_fix = sv_info->used_in_fix_mask & shift;
> +        sv.azimuth = sv_info->sv_list[i].elevation * location::units::Degrees;
> +        sv.elevation = sv_info->sv_list[i].azimuth * location::units::Degrees;
> +
> +        svs.insert(sv);
> +    }
> +
> +    thiz->space_vehicle_updates()(svs);
> +}
> +
> +void android::HardwareAbstractionLayer::on_set_capabilities(uint32_t capabilities, void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__;
> +
> +    auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +    thiz->capabilities() = capabilities;
> +}
> +
> +void android::HardwareAbstractionLayer::on_agps_status_update(UHardwareGpsAGpsStatus* status, void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__;
> +
> +    if (status->type == U_HARDWARE_GPS_AGPS_TYPE_C2K)
> +    {
> +        VLOG(1) << "\t We only support SUPL at this point in time.";
> +        return;
> +    }
> +
> +    auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +    thiz->impl.supl_assistant.status() = static_cast<gps::HardwareAbstractionLayer::SuplAssistant::Status>(status->status);
> +    thiz->impl.supl_assistant.server_ip() = gps::HardwareAbstractionLayer::SuplAssistant::IpV4Address{status->ipaddr};
> +
> +    VLOG(1) << int(thiz->impl.supl_assistant.status().get()) << ", "
> +            << status->ipaddr << ", "
> +            << (int)thiz->impl.supl_assistant.server_ip().get().triplets[0] << "."
> +            << (int)thiz->impl.supl_assistant.server_ip().get().triplets[1] << "."
> +            << (int)thiz->impl.supl_assistant.server_ip().get().triplets[2] << "."
> +            << (int)thiz->impl.supl_assistant.server_ip().get().triplets[3];
> +
> +    switch (status->status)
> +    {
> +    case U_HARDWARE_GPS_REQUEST_AGPS_DATA_CONN:
> +        VLOG(1) << "U_HARDWARE_GPS_REQUEST_AGPS_DATA_CONN";
> +        break;
> +    case U_HARDWARE_GPS_RELEASE_AGPS_DATA_CONN:
> +        VLOG(1) << "U_HARDWARE_GPS_RELEASE_AGPS_DATA_CONN";
> +        break;
> +    case U_HARDWARE_GPS_AGPS_DATA_CONNECTED:
> +        VLOG(1) << "U_HARDWARE_GPS_AGPS_DATA_CONNECTED";
> +        break;
> +    case U_HARDWARE_GPS_AGPS_DATA_CONN_DONE:
> +        VLOG(1) << "U_HARDWARE_GPS_AGPS_DATA_CONN_DONE";
> +        break;
> +    case U_HARDWARE_GPS_AGPS_DATA_CONN_FAILED:
> +        VLOG(1) << "U_HARDWARE_GPS_AGPS_DATA_CONN_FAILED";
> +        break;
> +    }
> +}
> +
> +void android::HardwareAbstractionLayer::on_request_utc_time(void* context)
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__;
> +
> +    auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +
> +    if (thiz->impl.utc_time_request_handler)
> +    {
> +        thiz->impl.utc_time_request_handler();
> +    } else
> +    {
> +        auto now = location::Clock::now().time_since_epoch();
> +        auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
> +
> +        static const int zero_uncertainty = 0;
> +
> +        u_hardware_gps_inject_time(
> +                    thiz->impl.gps_handle,
> +                    now.count(),
> +                    now.count(),
> +                    zero_uncertainty);
> +    }
> +}
> +
> +android::HardwareAbstractionLayer::HardwareAbstractionLayer(const android::HardwareAbstractionLayer::Configuration& config)
> +    : impl(this, config)
> +{
> +}
> +
> +std::uint32_t android::HardwareAbstractionLayer::capabilities() const
> +{
> +    return impl.capabilities;
> +}
> +
> +std::uint32_t& android::HardwareAbstractionLayer::capabilities()
> +{
> +    return impl.capabilities;
> +}
> +
> +// From gps::HardwareAbstractionLayer
> +gps::HardwareAbstractionLayer::SuplAssistant& android::HardwareAbstractionLayer::supl_assistant()
> +{
> +    return impl.supl_assistant;
> +}
> +
> +const core::Signal<location::Position>& android::HardwareAbstractionLayer::position_updates() const
> +{
> +    return impl.position_updates;
> +}
> +
> +core::Signal<location::Position>& android::HardwareAbstractionLayer::position_updates()
> +{
> +    return impl.position_updates;
> +}
> +
> +const core::Signal<location::Heading>& android::HardwareAbstractionLayer::heading_updates() const
> +{
> +    return impl.heading_updates;
> +}
> +
> +core::Signal<location::Heading>& android::HardwareAbstractionLayer::heading_updates()
> +{
> +    return impl.heading_updates;
> +}
> +
> +const core::Signal<location::Velocity>& android::HardwareAbstractionLayer::velocity_updates() const
> +{
> +    return impl.velocity_updates;
> +}
> +
> +core::Signal<location::Velocity>& android::HardwareAbstractionLayer::velocity_updates()
> +{
> +    return impl.velocity_updates;
> +}
> +
> +const core::Signal<std::set<location::SpaceVehicle> >& android::HardwareAbstractionLayer::space_vehicle_updates() const
> +{
> +    return impl.space_vehicle_updates;
> +}
> +
> +core::Signal<std::set<location::SpaceVehicle> >& android::HardwareAbstractionLayer::space_vehicle_updates()
> +{
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +    return impl.space_vehicle_updates;
> +}
> +
> +void android::HardwareAbstractionLayer::delete_all_aiding_data()
> +{
> +    // TODO(tvoss): We should expose this flag in gps.h.
> +    static const std::uint16_t delete_all = 0xFFFF;
> +    u_hardware_gps_delete_aiding_data(impl.gps_handle, delete_all);
> +}
> +
> +const core::Property<gps::ChipsetStatus>& android::HardwareAbstractionLayer::chipset_status() const
> +{
> +    return impl.chipset_status;
> +}
> +
> +core::Property<gps::ChipsetStatus>& android::HardwareAbstractionLayer::chipset_status()
> +{
> +    return impl.chipset_status;
> +}
> +
> +bool android::HardwareAbstractionLayer::is_capable_of(gps::AssistanceMode mode) const
> +{
> +    bool result = false;
> +
> +    switch(mode)
> +    {
> +    case gps::AssistanceMode::standalone:
> +        result = true;
> +        break;
> +    case gps::AssistanceMode::mobile_station_assisted:
> +        result = capabilities() & U_HARDWARE_GPS_CAPABILITY_MSA;
> +        break;
> +    case gps::AssistanceMode::mobile_station_based:
> +        result = capabilities() & U_HARDWARE_GPS_CAPABILITY_MSB;
> +        break;
> +    }
> +
> +    return result;
> +}
> +
> +bool android::HardwareAbstractionLayer::is_capable_of(gps::PositionMode mode) const
> +{
> +    bool result = false;
> +    switch(mode)
> +    {
> +    case gps::PositionMode::single_shot:
> +        result = capabilities() & U_HARDWARE_GPS_CAPABILITY_SINGLE_SHOT;
> +        break;
> +    case gps::PositionMode::periodic:
> +        result = capabilities() & U_HARDWARE_GPS_CAPABILITY_SCHEDULING;
> +        break;
> +    }
> +
> +    return result;
> +}
> +
> +bool android::HardwareAbstractionLayer::is_capable_of(gps::Capability capability) const
> +{
> +    bool result = false;
> +
> +    switch(capability)
> +    {
> +    case gps::Capability::on_demand_time_injection:
> +        result = capabilities() & U_HARDWARE_GPS_CAPABILITY_ON_DEMAND_TIME;
> +        break;
> +    default:
> +        break;
> +    }
> +
> +    return result;
> +}
> +
> +bool android::HardwareAbstractionLayer::start_positioning()
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": " << this << ", " << impl.gps_handle;
> +    return u_hardware_gps_start(impl.gps_handle);
> +}
> +
> +bool android::HardwareAbstractionLayer::stop_positioning()
> +{
> +    VLOG(1) << __PRETTY_FUNCTION__ << ": " << this << ", " << impl.gps_handle;
> +    return u_hardware_gps_stop(impl.gps_handle);
> +}
> +
> +bool android::HardwareAbstractionLayer::set_assistance_mode(gps::AssistanceMode mode)
> +{
> +    if (!is_capable_of(mode))
> +        return false;
> +
> +    impl.assistance_mode = mode;
> +    return impl.dispatch_updated_modes_to_driver();
> +}
> +
> +bool android::HardwareAbstractionLayer::set_position_mode(gps::PositionMode mode)
> +{
> +    switch(mode)
> +    {
> +    case gps::PositionMode::single_shot:
> +        if (!(capabilities() & U_HARDWARE_GPS_CAPABILITY_SINGLE_SHOT))
> +            return false;
> +        break;
> +    case gps::PositionMode::periodic:
> +        if (!(capabilities() & U_HARDWARE_GPS_CAPABILITY_SCHEDULING))
> +            return false;
> +        break;
> +    }
> +
> +    impl.position_mode = mode;
> +    return impl.dispatch_updated_modes_to_driver();
> +}
> +
> +bool android::HardwareAbstractionLayer::inject_reference_position(const location::Position& position)
> +{
> +    // TODO(tvoss): We should expose the int return type of the underyling
> +    //  Android HAL to capture errors here.
> +    UHardwareGpsLocation loc;
> +    loc.size = sizeof(loc);
> +    loc.flags = U_HARDWARE_GPS_LOCATION_HAS_LAT_LONG;
> +    loc.latitude = position.latitude.value.value();
> +    loc.longitude = position.longitude.value.value();
> +
> +    if (position.accuracy.horizontal)
> +    {
> +        loc.flags |= U_HARDWARE_GPS_LOCATION_HAS_ACCURACY;
> +        loc.accuracy = (*position.accuracy.horizontal).value();
> +    }
> +
> +    u_hardware_gps_inject_location(impl.gps_handle, loc);
> +
> +    return true;
> +}
> +
> +bool android::HardwareAbstractionLayer::inject_reference_time(
> +        const std::chrono::microseconds& reference_time,
> +        const std::chrono::microseconds& sample_time)
> +{
> +    if (!is_capable_of(gps::Capability::on_demand_time_injection))
> +        return false;
> +
> +    // TODO(tvoss): We should expose the int return type of the underyling
> +    //  Android HAL to capture errors here.
> +    u_hardware_gps_inject_time(impl.gps_handle,
> +                               reference_time.count(),
> +                               sample_time.count(),
> +                               10);
> +    return true;
> +}
> +
> +android::HardwareAbstractionLayer::Impl::Impl(
> +        android::HardwareAbstractionLayer* parent,
> +        const android::HardwareAbstractionLayer::Configuration& configuration)
> +    : capabilities(0),
> +      assistance_mode(gps::AssistanceMode::mobile_station_based),
> +      position_mode(gps::PositionMode::periodic),
> +      supl_assistant(*parent),
> +      gps_xtra_configuration(configuration.gps_xtra.configuration),
> +      gps_xtra_downloader(configuration.gps_xtra.downloader)
> +{
> +    ::memset(&gps_params, 0, sizeof(gps_params));
> +
> +    gps_params.location_cb = HardwareAbstractionLayer::on_location_update;
> +    gps_params.status_cb = HardwareAbstractionLayer::on_status_update;
> +    gps_params.sv_status_cb = HardwareAbstractionLayer::on_sv_status_update;
> +    gps_params.set_capabilities_cb = HardwareAbstractionLayer::on_set_capabilities;
> +    gps_params.request_utc_time_cb = HardwareAbstractionLayer::on_request_utc_time;
> +    gps_params.agps_status_cb = HardwareAbstractionLayer::on_agps_status_update;
> +
> +    gps_params.nmea_cb = HardwareAbstractionLayer::on_nmea_update;
> +    gps_params.xtra_download_request_cb = HardwareAbstractionLayer::on_xtra_download_request;
> +    gps_params.gps_ni_notify_cb = HardwareAbstractionLayer::on_gps_ni_notify;
> +    gps_params.request_setid_cb = HardwareAbstractionLayer::on_ril_request_set_id;
> +    gps_params.request_refloc_cb = HardwareAbstractionLayer::on_ril_request_reference_location;
> +
> +    gps_params.context = parent;
> +
> +    gps_handle = u_hardware_gps_new(std::addressof(gps_params));
> +
> +    dispatch_updated_modes_to_driver();
> +}
> +
> +bool android::HardwareAbstractionLayer::Impl::dispatch_updated_modes_to_driver()
> +{
> +    static const std::map<gps::AssistanceMode, std::uint32_t> assistance_mode_lut =
> +    {
> +        {gps::AssistanceMode::mobile_station_assisted, U_HARDWARE_GPS_POSITION_MODE_MS_ASSISTED},
> +        {gps::AssistanceMode::mobile_station_based, U_HARDWARE_GPS_POSITION_MODE_MS_BASED},
> +        {gps::AssistanceMode::standalone, U_HARDWARE_GPS_POSITION_MODE_STANDALONE}
> +    };
> +
> +    static const std::map<gps::PositionMode, std::uint32_t> position_mode_lut =
> +    {
> +        {gps::PositionMode::periodic, U_HARDWARE_GPS_POSITION_RECURRENCE_PERIODIC},
> +        {gps::PositionMode::single_shot, U_HARDWARE_GPS_POSITION_RECURRENCE_SINGLE}
> +    };
> +
> +    auto am = assistance_mode_lut.at(assistance_mode);
> +    auto pm = position_mode_lut.at(position_mode);
> +
> +    static const uint32_t preferred_accuracy_in_meters = 0;
> +    static const uint32_t preferred_ttff_in_ms = 0;
> +    static const std::chrono::milliseconds min_interval{500};
> +
> +    return u_hardware_gps_set_position_mode(
> +                gps_handle,
> +                am,
> +                pm,
> +                min_interval.count(),
> +                preferred_accuracy_in_meters,
> +                preferred_ttff_in_ms);
> +}
> +
> +namespace
> +{
> +std::ifstream etc_gps_conf{"/etc/gps.conf"};
> +}
> +
> +std::shared_ptr<gps::HardwareAbstractionLayer> gps::HardwareAbstractionLayer::create_default_instance()
> +{
> +    static android::HardwareAbstractionLayer::Configuration config
> +    {
> +        {
> +            create_xtra_downloader(),
> +            android::GpsXtraDownloader::Configuration::from_gps_conf_ini_file(etc_gps_conf)
> +        }
> +    };
> +
> +    static std::shared_ptr<gps::HardwareAbstractionLayer> instance
> +    {
> +        new android::HardwareAbstractionLayer
> +        {
> +            config
> +        }
> +    };
> +
> +    return instance;
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h'
> --- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,278 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_ANDROID_HARDWARE_ABSTRACTION_LAYER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_ANDROID_HARDWARE_ABSTRACTION_LAYER_H_
> +
> +#include <com/ubuntu/location/providers/gps/hardware_abstraction_layer.h>
> +
> +#include <ubuntu/hardware/gps.h>
> +
> +namespace com { namespace ubuntu { namespace location { namespace providers { namespace gps
> +{
> +namespace android
> +{
> +
> +/** @brief Models a downloader for GPS xtra data from HTTP sources. */
> +struct GpsXtraDownloader
> +{
> +    static constexpr const char* x_wap_profile_key
> +    {
> +        "x-wap-profile"
> +    };
> +
> +    static constexpr const char* x_wap_profile_value
> +    {
> +        "http://www.openmobilealliance.org/tech/profiles/UAPROF/ccppschema-20021212#"
> +    };
> +
> +    /** @brief Configuration options specific to a GpsXtraDownloader implementation. */
> +    struct Configuration
> +    {
> +        /** @brief Reads a configuration from a gps.conf file in INI format. */
> +        static Configuration from_gps_conf_ini_file(std::istream& in);
> +
> +        /** @brief Timeout on gps xtra download operations. */
> +        std::chrono::milliseconds timeout
> +        {
> +            1500
> +        };
> +
> +        /** Set of hosts serving GPS xtra data. */
> +        std::vector<std::string> xtra_hosts
> +        {
> +        };
> +    };
> +
> +    GpsXtraDownloader() = default;
> +    virtual ~GpsXtraDownloader() = default;
> +
> +    /** brief Downloads a GPS xtra data package from one of the servers given in config. */
> +    virtual std::vector<char> download_xtra_data(const Configuration& config) = 0;
> +};
> +
> +struct HardwareAbstractionLayer : public gps::HardwareAbstractionLayer
> +{
> +    /** @brief Implements gps::HardwareAbstractionLayer::SuplAssistant interface for the android gps HAL. */
> +    struct SuplAssistant : public gps::HardwareAbstractionLayer::SuplAssistant
> +    {
> +        /** @brief Bootstraps access to the Android GPS HAL assistance features. */
> +        SuplAssistant(android::HardwareAbstractionLayer& hal);
> +        /** @brief Getable/observable access to the status of the assistant instance. */
> +        const core::Property<Status>& status() const override;
> +        /** @brief Getable/setable/observable access to the status of the assistant instance. */
> +        core::Property<Status>& status();
> +        /** @brief Getable/observable access to the ip the assistance instance uses. */
> +        const core::Property<IpV4Address>& server_ip() const override;
> +        /** @brief Getable/setable/observable access to the ip the assistance instance uses. */
> +        core::Property<IpV4Address>& server_ip();
> +        /** @brief Informs the assistant instance about the SUPL server it should talk to. */
> +        void set_server(const std::string& host_name, std::uint16_t port) override;
> +        /** @brief Notifies the assistant instance that a data connection is open now. */
> +        void notify_data_connection_open_via_apn(const std::string& name) override;
> +        /** @brief Notifies the assistant instance the the data connection is closed now. */
> +        void notify_data_connection_closed() override;
> +        /** @brief Notifies the assistant instance that a data connection is not available right now. */
> +        void notify_data_connection_not_available() override;
> +
> +        struct Impl
> +        {
> +            Impl(android::HardwareAbstractionLayer& hal);
> +
> +            // The parent HardwareAbstractionLayer instance.
> +            android::HardwareAbstractionLayer& hal;
> +            // The status of the assisted GPS HAL.
> +            core::Property<gps::HardwareAbstractionLayer::SuplAssistant::Status> status;
> +            // The SUPL server address as reported by the Android GPS HAL.
> +            core::Property<gps::HardwareAbstractionLayer::SuplAssistant::IpV4Address> server_ip;
> +        } impl;
> +    };
> +
> +    /**
> +     * @brief Called whenever new NMEA data is available from the chipset.
> +     * @param [in] timestamp Indicates the time when the NMEA sentence was generated in the chipset.
> +     * @param [in] nmea NMEA sentence.
> +     * @param [in] length Length of the NMEA sentence.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_nmea_update(int64_t timestamp, const char *nmea, int length, void *context);
> +
> +    /**
> +     * @brief Called whenever the chipset requests GPS xtra data.
> +     * @param context The app-specific callback context.
> +     */
> +    static void on_xtra_download_request(void* context);
> +
> +    /**
> +     * @brief Called whenever a new network-initiated message is available.
> +     * @param [in] notification The notification object.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_gps_ni_notify(UHardwareGpsNiNotification* notification, void* context);
> +
> +    /**
> +     * @brief Called by the chipset for RIL-specific ID generation.
> +     * @param [in] flags The flags for the request
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_ril_request_set_id(uint32_t flags, void* context);
> +
> +    /**
> +     * @brief Called whenever the GPS chipsets requires cell information from RIL.
> +     * @param [in] flags The flags for the request.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_ril_request_reference_location(uint32_t flags, void* context);
> +
> +    /**
> +     * @brief Called whenever the GPS chipsets has got a location update available.
> +     * @param [in] location The new location.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_location_update(UHardwareGpsLocation* location, void* context);
> +
> +    /**
> +     * @brief Called whenever the GPS chipset status changes.
> +     * @param [in] status The new status of the GPS chipset.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_status_update(uint16_t status, void* context);
> +
> +    /**
> +     * @brief Called whenever satellite visibility changes.
> +     * @param [in] sv_info The new satellite visibility info.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_sv_status_update(UHardwareGpsSvStatus* sv_info, void* context);
> +
> +    /**
> +     * @brief Called to report the GPS chipset's capabilities
> +     * @param [in] capabilities Bitfield of capability flags.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_set_capabilities(uint32_t capabilities, void* context);
> +
> +    /**
> +     * @brief Called to report assisted gps status updates.
> +     * @param [in] status The new assisted gps status.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_agps_status_update(UHardwareGpsAGpsStatus* status, void* context);
> +
> +    /**
> +     * @brief Called whenever the GPS chipsets requires a reference time.
> +     * @param [in] context The app-specific callback context.
> +     */
> +    static void on_request_utc_time(void* context);
> +
> +    struct Configuration
> +    {
> +        struct
> +        {
> +            std::shared_ptr<GpsXtraDownloader> downloader;
> +            GpsXtraDownloader::Configuration configuration;
> +        } gps_xtra;
> +    };
> +
> +    HardwareAbstractionLayer(const Configuration& configuration);
> +
> +    /** @brief Reports the raw android capabilities. */
> +    std::uint32_t capabilities() const;
> +
> +    /** @brief Reports the raw android capabilities. */
> +    std::uint32_t& capabilities();
> +
> +    // From gps::HardwareAbstractionLayer
> +    gps::HardwareAbstractionLayer::SuplAssistant& supl_assistant() override;
> +
> +    const core::Signal<location::Position>& position_updates() const override;
> +    core::Signal<location::Position>& position_updates();
> +
> +    const core::Signal<location::Heading>& heading_updates() const override;
> +    core::Signal<location::Heading>& heading_updates();
> +
> +    const core::Signal<location::Velocity>& velocity_updates() const override;
> +    core::Signal<location::Velocity>& velocity_updates();
> +
> +    const core::Signal<std::set<location::SpaceVehicle> >& space_vehicle_updates() const override;
> +    core::Signal<std::set<location::SpaceVehicle> >& space_vehicle_updates();
> +
> +    void delete_all_aiding_data() override;
> +
> +    const core::Property<gps::ChipsetStatus>& chipset_status() const override;
> +    core::Property<gps::ChipsetStatus>& chipset_status();
> +
> +    bool is_capable_of(gps::AssistanceMode mode) const override;
> +    bool is_capable_of(gps::PositionMode mode) const override;
> +    bool is_capable_of(gps::Capability capability) const override;
> +
> +    bool start_positioning() override;
> +    bool stop_positioning() override;
> +
> +    bool set_assistance_mode(gps::AssistanceMode mode) override;
> +    bool set_position_mode(gps::PositionMode mode) override;
> +
> +    bool inject_reference_position(const location::Position& position) override;
> +    bool inject_reference_time(const std::chrono::microseconds& reference_time,
> +                               const std::chrono::microseconds& sample_time) override;
> +    struct Impl
> +    {
> +        // Bootstraps access to the GPS chipset, wiring up all callbacks.
> +        Impl(android::HardwareAbstractionLayer* parent, const android::HardwareAbstractionLayer::Configuration& configuration);
> +
> +        // Adjusts the assistance and positioning mode in one go, returning false in case of issues.
> +        bool dispatch_updated_modes_to_driver();
> +
> +        // The parameter bundle for the hardware GPS instance.
> +        UHardwareGpsParams gps_params;
> +        // The actual handle to the hardware GPS instance.
> +        UHardwareGps gps_handle;
> +
> +        // Capabilities bitfield for the hardware GPS instance.
> +        std::uint32_t capabilities;
> +        // The current assistance mode.
> +        gps::AssistanceMode assistance_mode;
> +        // The current position mode.
> +        gps::PositionMode position_mode;
> +
> +        // An implementation of the gps::HardwareAbstractionLayer::SuplAssistant interface.
> +        SuplAssistant supl_assistant;
> +
> +        // Callback for handling utc time requests.
> +        gps::HardwareAbstractionLayer::UtcTimeRequestHandler utc_time_request_handler;
> +
> +        // Emitted whenever the set of visible space vehicles changes.
> +        core::Signal<std::set<location::SpaceVehicle>> space_vehicle_updates;
> +        // Emitted whenever the position as reported by the GPS chipset changes.
> +        core::Signal<location::Position> position_updates;
> +        // Emitted whenever the heading as reported by the GPS chipset changes.
> +        core::Signal<location::Heading> heading_updates;
> +        // Emitted whenever the velocity as reported by the GPS chipset changes.
> +        core::Signal<location::Velocity> velocity_updates;
> +        // Emitted whenever the chipset status changes.
> +        core::Property<gps::ChipsetStatus> chipset_status;
> +
> +        // GPS Xtra configuration.
> +        GpsXtraDownloader::Configuration gps_xtra_configuration;
> +        // GPS xtra downloader implementation.
> +        std::shared_ptr<GpsXtraDownloader> gps_xtra_downloader;
> +    } impl;
> +};
> +}
> +}}}}}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_ANDROID_HARDWARE_ABSTRACTION_LAYER_H_
> 
> === added file 'src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.h'
> --- src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,323 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_HARDWARE_ABSTRACTION_LAYER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_HARDWARE_ABSTRACTION_LAYER_H_
> +
> +#include <com/ubuntu/location/heading.h>
> +#include <com/ubuntu/location/position.h>
> +#include <com/ubuntu/location/space_vehicle.h>
> +#include <com/ubuntu/location/velocity.h>
> +
> +#include <core/property.h>
> +
> +#include <chrono>
> +#include <iosfwd>
> +#include <memory>
> +#include <cstdint>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +namespace providers
> +{
> +namespace gps
> +{
> +/**
> + * @brief The ChipsetStatus enum summarizes the gps chipset status.
> + */
> +enum class ChipsetStatus
> +{
> +    /** Status is unknown. */
> +    unknown = 0,
> +    /** Chipset has begun navigating. */
> +    session_begin = 1,
> +    /** Chipset has stopped navigating. */
> +    session_end = 2,
> +    /** Chipset is powered on. */
> +    engine_on = 3,
> +    /** Chipset is powered off. */
> +    engine_off = 4
> +};
> +
> +/**
> + * @brief The Capabilities enum summarizes chipset capabilities.
> + */
> +enum class Capability
> +{
> +    /** The GPS chipset supports on-demand time injection. */
> +    on_demand_time_injection
> +};
> +
> +/**
> + * @brief The AssistanceMode enum summarizes the different assisted gps modes that
> + * the provider supports.
> + */
> +enum class AssistanceMode
> +{
> +    /** Provider runs on its own without any external assistance. */
> +    standalone,
> +
> +    /** In MSB mode A-GPS operation, the A-GPS device receives ephemeris,
> +     * reference location, reference time and other optional assistance data from the A-GPS server.
> +     * With the help of the above data, the A-GPS device receives signals from
> +     * the visible satellites and calculates the position.
> +     */
> +    mobile_station_based,
> +
> +    /** In MSA mode A-GPS operation, the A-GPS capable device receives acquisition assistance,
> +     * reference time and other optional assistance data from a mobile service provider.
> +     * The mobile service provider continuously logs GPS information (mainly the almanac) from
> +     * the GPS satellites using a A-GPS server in its system. With the help of the
> +     * above data (the data received from the mobile device and the data already present in A-GPS server)
> +     * the A-GPS server calculates the position and sends it back to the A-GPS device.
> +     */
> +    mobile_station_assisted
> +};
> +
> +enum class PositionMode
> +{
> +    /** Continually provide position updates. */
> +    periodic,
> +
> +    /** Obtain a single position estimate. */
> +    single_shot
> +};
> +
> +class HardwareAbstractionLayer
> +{
> +public:
> +
> +    class SuplAssistant
> +    {
> +    public:
> +        /**
> +         * @brief Simple union for reinterpreting an IP address given as a 32bit unsigned integer into the 4 triplets.
> +         */
> +        union IpV4Address
> +        {
> +            IpV4Address(std::uint32_t ip = 0) : ip(ip)
> +            {
> +            }
> +
> +            inline bool operator==(const IpV4Address& rhs) const
> +            {
> +                return ip == rhs.ip;
> +            }
> +
> +            inline bool operator!=(const IpV4Address& rhs) const
> +            {
> +                return ip != rhs.ip;
> +            }
> +
> +            std::uint32_t ip;
> +            std::uint8_t triplets[4];
> +        };
> +
> +        /**
> +         * @brief Current status of a SuplAssistant instance.
> +         */
> +        enum class Status
> +        {
> +            /** The assistant requires a data connection. */
> +            request_data_connection = 1,
> +            /** The assistant no longer requires a data connection. */
> +            release_data_connection = 2,
> +            /** The data connection has been initiated. */
> +            data_connection_initiated = 3,
> +            /** The data transfer has been successfully completed. */
> +            data_connection_completed = 4,
> +            /** The data transfer failed. */
> +            data_connection_failed = 5
> +        };
> +
> +        virtual ~SuplAssistant() = default;
> +        SuplAssistant(const SuplAssistant&) = delete;
> +
> +        SuplAssistant& operator=(const SuplAssistant&) = delete;
> +        bool operator==(const SuplAssistant&) = delete;
> +
> +        /**
> +         * @brief Getable/observable access to the status of the assistant instance.
> +         */
> +        virtual const core::Property<Status>& status() const = 0;
> +
> +        /**
> +         * @brief Getable/observable access to the ip the assistance instance uses.
> +         */
> +        virtual const core::Property<IpV4Address>& server_ip() const = 0;
> +
> +        /**
> +         * @brief set_server informs the assistant instance about the SUPL server it should talk to.
> +         * @param host_name The host name of the SUPL server.
> +         * @param port The port of the SUPL server.
> +         */
> +        virtual void set_server(const std::string& host_name, std::uint16_t port) = 0;
> +
> +        /**
> +          * @brief Notifies the assistant instance that a data connection is open now.
> +          */
> +        virtual void notify_data_connection_open_via_apn(const std::string& name) = 0;
> +
> +        /**
> +          * @brief Notifies the assistant instance the the data connection is closed now.
> +          */
> +        virtual void notify_data_connection_closed() = 0;
> +
> +        /**
> +          * @brief Notifies the assistant instance that a data connection is not available right now.
> +          */
> +        virtual void notify_data_connection_not_available() = 0;
> +
> +    protected:
> +        SuplAssistant() = default;
> +    };
> +
> +    /**
> +     * @brief UtcTimeRequestHandler handles chipset requests for time synchronization
> +     *
> +     * An implementation is expected to provide the new reference time in
> +     * milliseconds since 01.01.1970 to the chipset via a call to inject reference time.
> +     */
> +    typedef std::function<void()> UtcTimeRequestHandler;
> +
> +    /**
> +     * @brief Returns the default instance for accessing the actual HW.
> +     */
> +    static std::shared_ptr<HardwareAbstractionLayer> create_default_instance();
> +
> +    virtual ~HardwareAbstractionLayer() = default;
> +
> +    HardwareAbstractionLayer(const HardwareAbstractionLayer&) = delete;
> +    HardwareAbstractionLayer& operator=(const HardwareAbstractionLayer&) = delete;
> +    bool operator==(const HardwareAbstractionLayer&) const = delete;
> +
> +    /**
> +     * @brief supl_assistant provides access to the SuplAssistant instance that the HAL is using.
> +     * @return A valid instance if the HAL uses assisted GPS or a nullptr if not.
> +     */
> +    virtual SuplAssistant& supl_assistant() = 0;
> +
> +    /**
> +     * @brief Signal for delivery of position updates.
> +     */
> +    virtual const core::Signal<Position>& position_updates() const = 0;
> +
> +    /**
> +     * @brief Signal for delivery of heading updates.
> +     */
> +    virtual const core::Signal<Heading>& heading_updates() const = 0;
> +
> +    /**
> +     * @brief Signal for delivery of velocity updates.
> +     */
> +    virtual const core::Signal<Velocity>& velocity_updates() const = 0;
> +
> +    /**
> +     * @brief Signal for delivery of satellite visibility updates.
> +     */
> +    virtual const core::Signal<std::set<SpaceVehicle>>& space_vehicle_updates() const = 0;
> +
> +    /**
> +      * @brief Requests the chipset to drop all aiding data, including almanac, ephimeris and ionospheric data.
> +      *
> +      * Calling this function results in a cold start the next time the positioning is initiated.
> +      *
> +      */
> +    virtual void delete_all_aiding_data() = 0;
> +
> +    /**
> +     * @brief Observable/getable property modelling the status of the chipset.
> +     * @return A non-mutable reference to the property.
> +     */
> +    virtual const core::Property<ChipsetStatus>& chipset_status() const = 0;
> +
> +    /**
> +     * @brief Checks whether the chipset and driver support the specified assistance mode.
> +     * @param mode The assistance mode to check for.
> +     * @return true iff chipset and driver support the specified mode.
> +     */
> +    virtual bool is_capable_of(AssistanceMode mode) const = 0;
> +
> +    /**
> +     * @brief Checks whether the chipset and driver support the specified position mode.
> +     * @param mode The position mode to check for.
> +     * @return true iff chipset and driver support the specified mode.
> +     */
> +    virtual bool is_capable_of(PositionMode mode) const = 0;
> +
> +    /**
> +     * @brief Checks whether the chipset and driver support the specified capability.
> +     * @param capability The capability to check for.
> +     * @return true iff chipset and driver support the specified capability.
> +     */
> +    virtual bool is_capable_of(Capability capability) const = 0;
> +
> +    /**
> +     * @brief Starts the actual positioning process of the underlying HW.
> +     * @return true iff starting the positioning engine was successful.
> +     */
> +    virtual bool start_positioning() = 0;
> +
> +    /**
> +     * @brief Stops the actual positioning process of the underlying HW.
> +     * @return true iff stopping the positioning engine was successful.
> +     */
> +    virtual bool stop_positioning() = 0;
> +
> +    /**
> +     * @brief Dispatches the requested mode change to the driver/hw.
> +     * @param mode The new assistance mode.
> +     * @return true iff the mode change was carried out successfully.
> +     */
> +    virtual bool set_assistance_mode(AssistanceMode mode) = 0;
> +
> +    /**
> +     * @brief Dispatches the requested mode change to the driver/hw.
> +     * @param mode The new position mode.
> +     * @return true iff the mode change was carried out successfully.
> +     */
> +    virtual bool set_position_mode(PositionMode mode) = 0;
> +
> +    /**
> +     * @brief Injects a reference position to the underlying gps driver/chipset.
> +     * @return true iff the injection was successful, false otherwise.
> +     */
> +    virtual bool inject_reference_position(const Position& position) = 0;
> +
> +    /**
> +     * @brief Injects a new reference time to the underlying gps driver/chipset.
> +     * @param reference_time The new reference time.
> +     * @param sample_time When the reference time was sampled.
> +     * @return true iff the injection was successful, false otherwise.
> +     */
> +    virtual bool inject_reference_time(const std::chrono::microseconds& reference_time,
> +                                       const std::chrono::microseconds& sample_time) = 0;
> +
> +protected:
> +    HardwareAbstractionLayer() = default;
> +};
> +}
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_HARDWARE_ABSTRACTION_LAYER_H_
> 
> === added file 'src/location_service/com/ubuntu/location/providers/gps/net_cpp_gps_xtra_downloader.cpp'
> === added file 'src/location_service/com/ubuntu/location/providers/gps/net_cpp_gps_xtra_downloader.h'
> --- src/location_service/com/ubuntu/location/providers/gps/net_cpp_gps_xtra_downloader.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/net_cpp_gps_xtra_downloader.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_NET_CPP_GPS_XTRA_DOWNLOADER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_NET_CPP_GPS_XTRA_DOWNLOADER_H_
> +
> +#include "android_hardware_abstraction_layer.h"
> +
> +#include <core/net/http/client.h>
> +#include <core/net/http/request.h>
> +#include <core/net/http/response.h>
> +
> +namespace com { namespace ubuntu { namespace location { namespace providers { namespace gps { namespace android {
> +struct NetCppGpsXtraDownloader : public GpsXtraDownloader
> +{
> +    NetCppGpsXtraDownloader() : http_client{core::net::http::make_client()}
> +    {
> +    }
> +
> +    /** @brief Executes the actual download, throws if no xtra servers are given in the config. */
> +    virtual std::vector<char> download_xtra_data(const Configuration& config) override
> +    {
> +        if (config.xtra_hosts.empty()) throw std::runtime_error
> +        {
> +            "Missing xtra hosts."
> +        };
> +
> +        std::uniform_int_distribution<std::size_t> dist{0, config.xtra_hosts.size() - 1};
> +
> +        auto host = config.xtra_hosts.at(dist(dre));
> +
> +        auto rc = core::net::http::Request::Configuration::from_uri_as_string(host);
> +
> +        rc.header.add("Accept", "*/*");
> +        rc.header.add("Accept", "application/vnd.wap.mms-message");
> +        rc.header.add("Accept", "application/vnd.wap.sic");
> +        rc.header.add(x_wap_profile_key, x_wap_profile_value);
> +
> +        auto request = http_client->get(rc);
> +        request->set_timeout(config.timeout);
> +
> +        auto response = request->execute([](const core::net::http::Request::Progress&)
> +        {
> +            return core::net::http::Request::Progress::Next::continue_operation;
> +        });
> +
> +        if (response.status != core::net::http::Status::ok)
> +        {
> +            std::stringstream ss{"Request for xtra data on "};
> +            ss << host << " did not succeed: " << response.status;
> +            throw std::runtime_error{ss.str()};
> +        }
> +
> +        return std::vector<char>(response.body.begin(), response.body.end());
> +    }
> +
> +    // Client instance to talk to xtra servers.
> +    std::shared_ptr<core::net::http::Client> http_client;
> +    // Random number generator for load balancing purposes.
> +    std::default_random_engine dre;
> +};
> +}}}}}}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_NET_CPP_GPS_XTRA_DOWNLOADER_H_
> 
> === added file 'src/location_service/com/ubuntu/location/providers/gps/null_gps_xtra_downloader.h'
> --- src/location_service/com/ubuntu/location/providers/gps/null_gps_xtra_downloader.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/null_gps_xtra_downloader.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,39 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_NULL_GPS_XTRA_DOWNLOADER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_NULL_GPS_XTRA_DOWNLOADER_H_
> +
> +#include "android_hardware_abstraction_layer.h"
> +
> +#include <com/ubuntu/location/logging.h>
> +
> +namespace com { namespace ubuntu { namespace location { namespace providers { namespace gps { namespace android {
> +/** @brief Implements a GPS xtra downloader that just logs download attempts. */
> +struct NullGpsXtraDownloader : public android::GpsXtraDownloader
> +{
> +    std::vector<char> download_xtra_data(const Configuration& config) override
> +    {
> +        VLOG(10) << __PRETTY_FUNCTION__ << "\n"
> +                 << "  Nr. xtra hosts: " << config.xtra_hosts.size();
> +
> +        return std::vector<char>{};
> +    }
> +};
> +}}}}}}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_NULL_GPS_XTRA_DOWNLOADER_H_
> 
> === modified file 'src/location_service/com/ubuntu/location/providers/gps/provider.cpp'
> --- src/location_service/com/ubuntu/location/providers/gps/provider.cpp	2013-10-17 10:27:43 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/provider.cpp	2014-06-24 16:02:38 +0000
> @@ -15,129 +15,24 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/providers/gps/provider.h"
> -
> -#include "com/ubuntu/location/logging.h"
> +
> +#include "provider.h"
> +
> +#include "hardware_abstraction_layer.h"
> +
> +#include <com/ubuntu/location/logging.h>
> +#include <com/ubuntu/location/connectivity/manager.h>
>  
>  #include <ubuntu/hardware/gps.h>
>  
>  namespace cul = com::ubuntu::location;
>  namespace culg = com::ubuntu::location::providers::gps;
>  
> -namespace
> -{
> -static const std::map<uint16_t, std::string> status_lut = 
> -{
> -    {U_HARDWARE_GPS_STATUS_NONE, "U_HARDWARE_GPS_STATUS_NONE"},
> -    {U_HARDWARE_GPS_STATUS_SESSION_BEGIN, "U_HARDWARE_GPS_STATUS_SESSION_BEGIN"},
> -    {U_HARDWARE_GPS_STATUS_SESSION_END, "U_HARDWARE_GPS_STATUS_SESSION_END"},
> -    {U_HARDWARE_GPS_STATUS_ENGINE_ON, "U_HARDWARE_GPS_STATUS_ENGINE_ON"},
> -    {U_HARDWARE_GPS_STATUS_ENGINE_OFF, "U_HARDWARE_GPS_STATUS_ENGINE_OFF"}
> -};
> -}
> -
>  struct culg::Provider::Private
>  {
> -
> -static void on_location_update(UHardwareGpsLocation* location, void* context)
> -{
> -    auto thiz = static_cast<culg::Provider*>(context);
> -        
> -    if (location->flags & U_HARDWARE_GPS_LOCATION_HAS_LAT_LONG)
> -    {
> -        VLOG(1) << "location->flags & U_HARDWARE_GPS_LOCATION_HAS_LAT_LONG";
> -
> -        cul::Position pos;
> -        pos.latitude(cul::wgs84::Latitude{location->latitude * cul::units::Degrees});
> -        pos.longitude(cul::wgs84::Longitude{location->longitude * cul::units::Degrees});
> -        if(location->flags & U_HARDWARE_GPS_LOCATION_HAS_ALTITUDE)
> -            pos.altitude(cul::wgs84::Altitude{location->altitude * cul::units::Meters});
> -        
> -        thiz->deliver_position_updates(cul::Update<cul::Position>{pos, cul::Clock::now()});
> -    }
> -    
> -    if (location->flags & U_HARDWARE_GPS_LOCATION_HAS_SPEED)
> -    {
> -        VLOG(1) << "location->flags & U_HARDWARE_GPS_LOCATION_HAS_SPEED";
> -        
> -        cul::Velocity v{location->speed * cul::units::MetersPerSecond};
> -        thiz->deliver_velocity_updates(cul::Update<cul::Velocity>{v, cul::Clock::now()});
> -    }
> -
> -    if (location->flags & U_HARDWARE_GPS_LOCATION_HAS_BEARING)
> -    {
> -        VLOG(1) << "location->flags & U_HARDWARE_GPS_LOCATION_HAS_BEARING";
> -        
> -        cul::Heading h{location->bearing * cul::units::Degrees};
> -        thiz->deliver_heading_updates(cul::Update<cul::Heading>{h, cul::Clock::now()});
> -    }
> -}
> -
> -static void on_status_update(uint16_t status, void* /*context*/)
> -{
> -    SYSLOG(INFO) << "Status = " << status_lut.at(status);
> -}
> -
> -static void on_sv_status_update(UHardwareGpsSvStatus* sv_info, void* /*context*/)
> -{
> -    SYSLOG_EVERY_N(INFO, 20) << "SV status update: [#svs: " << sv_info->num_svs << "]";
> -}
> -    
> -static void on_nmea_update(int64_t /*timestamp*/, const char* /*nmea*/, int /*length*/, void* /*context*/)
> -{
> -}
> -
> -static void on_set_capabilities(uint32_t capabilities, void* /*context*/)
> -{
> -    VLOG(1) << __PRETTY_FUNCTION__ << ": " << capabilities;
> -}
> -
> -static void on_request_utc_time(void* /*context*/)
> -{
> -    VLOG(1) << __PRETTY_FUNCTION__;
> -}
> -
> -static void on_agps_status_update(UHardwareGpsAGpsStatus* /*status*/, void* /*context*/)
> -{
> -    VLOG(1) << __PRETTY_FUNCTION__;
> -}
> -
> -static void on_gps_ni_notification(UHardwareGpsNiNotification* /*notification*/, void* /*context*/)
> -{
> -    VLOG(1) << __PRETTY_FUNCTION__;
> -}
> -    
> -static void on_agps_ril_request_set_id(uint32_t /*flags*/, void* /*context*/)
> -{
> -    VLOG(1) << __PRETTY_FUNCTION__;
> -}
> -
> -static void on_agps_ril_request_ref_lock(uint32_t /*flags*/, void* /*context*/)
> -{
> -    VLOG(1) << __PRETTY_FUNCTION__;
> -}
> -
> -    static void on_gps_xtra_download_request(void*)
> -    {
> -        VLOG(1) << __PRETTY_FUNCTION__;
> -    }
> -
> -    void start() 
> -    { 
> -        u_hardware_gps_start(gps_handle);
> -    }
> -    
> -    void stop() 
> -    { 
> -        u_hardware_gps_stop(gps_handle);
> -    }
> -
> -    UHardwareGpsParams gps_params;
> -    UHardwareGps gps_handle;
> +    std::shared_ptr<HardwareAbstractionLayer> hal;
>  };
>  
> -
> -
>  std::string culg::Provider::class_name()
>  {
>      return "gps::Provider";
> @@ -145,63 +40,41 @@
>  
>  cul::Provider::Ptr culg::Provider::create_instance(const cul::ProviderFactory::Configuration&)
>  {
> -    return cul::Provider::Ptr{new culg::Provider{}};
> -}
> -
> -const cul::Provider::FeatureFlags& culg::Provider::default_feature_flags()
> -{
> -    static const cul::Provider::FeatureFlags flags{"001"};
> -    return flags;
> -}
> -
> -const cul::Provider::RequirementFlags& culg::Provider::default_requirement_flags()
> -{
> -    static const cul::Provider::RequirementFlags flags{"1010"};
> -    return flags;
> -}
> -
> -culg::Provider::Provider()
> -        : cul::Provider(
> -              culg::Provider::default_feature_flags(), 
> -              culg::Provider::default_requirement_flags()),
> -          d(new Private())
> -{
> -    d->gps_params.location_cb = culg::Provider::Private::on_location_update;
> -    d->gps_params.status_cb = culg::Provider::Private::on_status_update;
> -    d->gps_params.sv_status_cb = culg::Provider::Private::on_sv_status_update;
> -    d->gps_params.nmea_cb = culg::Provider::Private::on_nmea_update;
> -    d->gps_params.set_capabilities_cb = culg::Provider::Private::on_set_capabilities;
> -    d->gps_params.request_utc_time_cb = culg::Provider::Private::on_request_utc_time;
> -    d->gps_params.xtra_download_request_cb = culg::Provider::Private::on_gps_xtra_download_request;
> -    
> -    d->gps_params.agps_status_cb = culg::Provider::Private::on_agps_status_update;
> -    
> -    d->gps_params.gps_ni_notify_cb = culg::Provider::Private::on_gps_ni_notification;
> -    
> -    d->gps_params.request_setid_cb = culg::Provider::Private::on_agps_ril_request_set_id;
> -    d->gps_params.request_refloc_cb = culg::Provider::Private::on_agps_ril_request_ref_lock;
> -    d->gps_params.context = this;
> -    
> -    d->gps_handle = u_hardware_gps_new(std::addressof(d->gps_params));
> -
> -    static const std::chrono::milliseconds minimum_interval{500};
> -    static const uint32_t preferred_accuracy{0};
> -    static const uint32_t preferred_time_to_first_fix{0};
> -
> -    u_hardware_gps_set_position_mode(
> -                d->gps_handle,
> -                U_HARDWARE_GPS_POSITION_MODE_MS_BASED,
> -                U_HARDWARE_GPS_POSITION_RECURRENCE_PERIODIC,
> -                minimum_interval.count(),
> -                preferred_accuracy,
> -                preferred_time_to_first_fix
> -                );
> +    return cul::Provider::Ptr{new culg::Provider{culg::HardwareAbstractionLayer::create_default_instance()}};
> +}
> +
> +culg::Provider::Provider(const std::shared_ptr<HardwareAbstractionLayer>& hal)
> +    : cul::Provider(
> +          cul::Provider::Features::position | cul::Provider::Features::velocity | cul::Provider::Features::heading,
> +          cul::Provider::Requirements::satellites),
> +      d(new Private())
> +{
> +    d->hal = hal;
> +
> +    d->hal->position_updates().connect([this](const location::Position& pos)
> +    {
> +        mutable_updates().position(Update<Position>(pos));
> +    });
> +
> +    d->hal->heading_updates().connect([this](const location::Heading& heading)
> +    {
> +        mutable_updates().heading(Update<Heading>(heading));
> +    });
> +
> +    d->hal->velocity_updates().connect([this](const location::Velocity& velocity)
> +    {
> +        mutable_updates().velocity(Update<Velocity>(velocity));
> +    });
> +
> +    d->hal->space_vehicle_updates().connect([this](const std::set<location::SpaceVehicle>& svs)
> +    {
> +        mutable_updates().svs(Update<std::set<location::SpaceVehicle>>(svs));
> +    });
>  }
>  
>  culg::Provider::~Provider() noexcept
>  {
> -    d->stop();
> -    u_hardware_gps_delete(d->gps_handle);
> +    d->hal->stop_positioning();
>  }
>  
>  bool culg::Provider::matches_criteria(const cul::Criteria&)
> @@ -211,30 +84,36 @@
>  
>  void culg::Provider::start_position_updates()
>  {
> -    d->start();
> +    d->hal->start_positioning();
>  }
>  
>  void culg::Provider::stop_position_updates()
>  {
> -    d->stop();
> +    d->hal->stop_positioning();
>  }
>  
>  void culg::Provider::start_velocity_updates()
>  {
> -    d->start();
> +    d->hal->start_positioning();
>  }
>  
>  void culg::Provider::stop_velocity_updates()
>  {
> -    d->stop();
> +    d->hal->stop_positioning();
>  }    
>  
>  void culg::Provider::start_heading_updates()
>  {
> -    d->start();
> +    d->hal->start_positioning();
>  }
>  
>  void culg::Provider::stop_heading_updates()
>  {
> -    d->stop();
> -}
> +    d->hal->stop_positioning();
> +}
> +
> +void culg::Provider::on_reference_location_updated(const cul::Update<cul::Position>& position)
> +{
> +    d->hal->inject_reference_position(position.value);
> +}
> +
> 
> === renamed file 'include/location_service/com/ubuntu/location/providers/gps/provider.h' => 'src/location_service/com/ubuntu/location/providers/gps/provider.h'
> --- include/location_service/com/ubuntu/location/providers/gps/provider.h	2013-05-28 14:41:06 +0000
> +++ src/location_service/com/ubuntu/location/providers/gps/provider.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,10 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_PROVIDER_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_PROVIDER_H_
>  
> -#include "com/ubuntu/location/provider.h"
> -#include "com/ubuntu/location/provider_factory.h"
> +#include <com/ubuntu/location/provider.h>
> +#include <com/ubuntu/location/provider_factory.h>
> +
> +#include "hardware_abstraction_layer.h"
>  
>  namespace com
>  {
> @@ -31,30 +33,31 @@
>  {
>  namespace gps
>  {
> +
>  class Provider : public com::ubuntu::location::Provider
>  {
>    public:
> +    // For integration with the Provider factory.
>      static std::string class_name();
>      static Provider::Ptr create_instance(const ProviderFactory::Configuration&);
>  
> -    static const Provider::FeatureFlags& default_feature_flags();
> -    static const Provider::RequirementFlags& default_requirement_flags();
> -
> -    Provider();
> +    Provider(const std::shared_ptr<HardwareAbstractionLayer>& hal = HardwareAbstractionLayer::create_default_instance());
>      Provider(const Provider&) = delete;
>      Provider& operator=(const Provider&) = delete;
>      ~Provider() noexcept;
>  
> -    virtual bool matches_criteria(const Criteria&);
> -
> -    virtual void start_position_updates();
> -    virtual void stop_position_updates();
> -
> -    virtual void start_velocity_updates();
> -    virtual void stop_velocity_updates();
> -
> -    virtual void start_heading_updates();
> -    virtual void stop_heading_updates();
> +    bool matches_criteria(const Criteria&);
> +
> +    void start_position_updates();
> +    void stop_position_updates();
> +
> +    void start_velocity_updates();
> +    void stop_velocity_updates();
> +
> +    void start_heading_updates();
> +    void stop_heading_updates();
> +
> +    void on_reference_location_updated(const Update<Position>& position);
>  
>    private:
>      struct Private;
> 
> === modified file 'src/location_service/com/ubuntu/location/providers/skyhook/provider.cpp'
> --- src/location_service/com/ubuntu/location/providers/skyhook/provider.cpp	2013-05-29 06:04:02 +0000
> +++ src/location_service/com/ubuntu/location/providers/skyhook/provider.cpp	2014-06-24 16:02:38 +0000
> @@ -15,10 +15,10 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/providers/skyhook/provider.h"
> +#include <com/ubuntu/location/providers/skyhook/provider.h>
>  
> -#include "com/ubuntu/location/logging.h"
> -#include "com/ubuntu/location/provider_factory.h"
> +#include <com/ubuntu/location/logging.h>
> +#include <com/ubuntu/location/provider_factory.h>
>  
>  #pragma GCC diagnostic push
>  #pragma GCC diagnostic warning "-Wignored-qualifiers"
> 
> === modified file 'src/location_service/com/ubuntu/location/proxy_provider.cpp'
> --- src/location_service/com/ubuntu/location/proxy_provider.cpp	2013-06-10 11:10:00 +0000
> +++ src/location_service/com/ubuntu/location/proxy_provider.cpp	2014-06-24 16:02:38 +0000
> @@ -15,18 +15,35 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/proxy_provider.h"
> +#include <com/ubuntu/location/proxy_provider.h>
>  
>  #include <bitset>
>  #include <memory>
>  
> +namespace cu = com::ubuntu;
>  namespace cul = com::ubuntu::location;
>  
>  cul::ProxyProvider::ProxyProvider(const cul::ProviderSelection& selection)
>      : Provider(selection.to_feature_flags()),
> -      position_updates_provider(selection.position_updates_provider),
> -      heading_updates_provider(selection.heading_updates_provider),
> -      velocity_updates_provider(selection.velocity_updates_provider)
> +      providers(selection),
> +      connections
> +      {
> +          providers.position_updates_provider->updates().position.connect(
> +              [this](const cul::Update<cul::Position>& u)
> +              {
> +                  mutable_updates().position(u);
> +              }),
> +          providers.heading_updates_provider->updates().heading.connect(
> +              [this](const cul::Update<cul::Heading>& u)
> +              {
> +                  mutable_updates().heading(u);
> +              }),
> +          providers.velocity_updates_provider->updates().velocity.connect(
> +              [this](const cul::Update<cul::Velocity>& u)
> +              {
> +                  mutable_updates().velocity(u);
> +              })
> +      }
>  {
>  }
>  
> @@ -34,59 +51,32 @@
>  {
>  }
>  
> -cul::ChannelConnection cul::ProxyProvider::subscribe_to_position_updates(std::function<void(const cul::Update<cul::Position>&)> f)
> -{
> -    if (position_updates_provider)
> -        return position_updates_provider->subscribe_to_position_updates(f);
> -    return ChannelConnection {};
> -}
> -
> -cul::ChannelConnection cul::ProxyProvider::subscribe_to_heading_updates(std::function<void(const cul::Update<cul::Heading>&)> f)
> -{
> -    if (heading_updates_provider)
> -        return heading_updates_provider->subscribe_to_heading_updates(f);
> -    return ChannelConnection {};
> -}
> -
> -cul::ChannelConnection cul::ProxyProvider::subscribe_to_velocity_updates(std::function<void(const cul::Update<cul::Velocity>&)> f)
> -{
> -    if (velocity_updates_provider)
> -        return velocity_updates_provider->subscribe_to_velocity_updates(f);
> -    return ChannelConnection {};
> -}
> -
>  void cul::ProxyProvider::start_position_updates()
>  {
> -    if (position_updates_provider)
> -        position_updates_provider->state_controller()->start_position_updates();
> +    providers.position_updates_provider->state_controller()->start_position_updates();
>  }
>  
>  void cul::ProxyProvider::stop_position_updates()
>  {
> -    if (position_updates_provider)
> -        position_updates_provider->state_controller()->stop_position_updates();
> +    providers.position_updates_provider->state_controller()->stop_position_updates();
>  }
>  
>  void cul::ProxyProvider::start_velocity_updates()
>  {
> -    if (velocity_updates_provider)
> -        velocity_updates_provider->state_controller()->start_velocity_updates();
> +    providers.velocity_updates_provider->state_controller()->start_velocity_updates();
>  }
>  
>  void cul::ProxyProvider::stop_velocity_updates()
>  {
> -    if (velocity_updates_provider)
> -        velocity_updates_provider->state_controller()->stop_velocity_updates();
> +    providers.velocity_updates_provider->state_controller()->stop_velocity_updates();
>  }    
>  
>  void cul::ProxyProvider::start_heading_updates()
>  {
> -    if (heading_updates_provider)
> -        heading_updates_provider->state_controller()->start_heading_updates();
> +    providers.heading_updates_provider->state_controller()->start_heading_updates();
>  }
>  
>  void cul::ProxyProvider::stop_heading_updates()
>  {
> -    if (heading_updates_provider)
> -        heading_updates_provider->state_controller()->stop_heading_updates();
> +    providers.heading_updates_provider->state_controller()->stop_heading_updates();
>  }
> 
> === added file 'src/location_service/com/ubuntu/location/service/daemon.cpp'
> --- src/location_service/com/ubuntu/location/service/daemon.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/daemon.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,467 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#include <com/ubuntu/location/provider_factory.h>
> +
> +#include <com/ubuntu/location/service/default_configuration.h>
> +#include <com/ubuntu/location/service/implementation.h>
> +#include <com/ubuntu/location/service/stub.h>
> +
> +#include "program_options.h"
> +#include "daemon.h"
> +
> +#include <core/dbus/announcer.h>
> +#include <core/dbus/resolver.h>
> +#include <core/dbus/asio/executor.h>
> +
> +#include <core/posix/signal.h>
> +
> +#include <system_error>
> +#include <thread>
> +
> +#include <signal.h>
> +#include <sys/signalfd.h>
> +
> +namespace location = com::ubuntu::location;
> +namespace dbus = core::dbus;
> +
> +namespace
> +{
> +struct NullReporter : public location::service::Harvester::Reporter
> +{
> +    NullReporter() = default;
> +
> +    /** @brief Tell the reporter that it should start operating. */
> +    void start()
> +    {
> +    }
> +
> +    /** @brief Tell the reporter to shut down its operation. */
> +    void stop()
> +    {
> +    }
> +
> +    /**
> +     * @brief Triggers the reporter to send off the information.
> +     */
> +    void report(const location::Update<location::Position>&,
> +                const std::vector<location::connectivity::WirelessNetwork::Ptr>&,
> +                const std::vector<location::connectivity::RadioCell::Ptr>&)
> +    {
> +    }
> +};
> +
> +location::ProgramOptions init_daemon_options()
> +{
> +    location::ProgramOptions options;
> +
> +    options.add("help", "Produces this help message");
> +    options.add("testing", "Enables running the service without providers");
> +    options.add_composed<std::vector<std::string>>("provider",
> +                                                   "The providers that should be added to the engine");
> +
> +    return options;
> +}
> +
> +location::ProgramOptions& mutable_daemon_options()
> +{
> +    static location::ProgramOptions options = init_daemon_options();
> +    return options;
> +}
> +}
> +
> +location::service::Daemon::Configuration location::service::Daemon::Configuration::from_command_line_args(
> +        int argc,
> +        char** argv,
> +        location::service::Daemon::DBusConnectionFactory factory)
> +{
> +    location::service::Daemon::Configuration result;
> +
> +    if (!mutable_daemon_options().parse_from_command_line_args(argc, (const char**)argv))
> +        throw std::runtime_error{"Could not parse command-line, aborting..."};
> +
> +    result.incoming = factory(mutable_daemon_options().bus());
> +    result.outgoing= factory(mutable_daemon_options().bus());
> +
> +    if (mutable_daemon_options().value_count_for_key("testing") == 0 && mutable_daemon_options().value_count_for_key("provider") == 0)
> +    {
> +        std::stringstream ss;
> +        ss << "A set of providers need to be specified. The following providers are known:" << std::endl;
> +        location::ProviderFactory::instance().enumerate(
> +                    [&ss](const std::string& name, const location::ProviderFactory::Factory&)
> +        {
> +            ss << "\t" << name << std::endl;
> +        });
> +        throw std::runtime_error{ss.str()};
> +    }
> +
> +    if(mutable_daemon_options().value_count_for_key("provider") > 0)
> +    {
> +        result.providers = mutable_daemon_options().value_for_key<std::vector<std::string>>("provider");
> +
> +        for (const std::string& provider : result.providers)
> +        {
> +            mutable_daemon_options().enumerate_unrecognized_options(
> +                        [&result, provider](const std::string& s)
> +            {
> +                std::stringstream in(s);
> +                std::string key, value;
> +
> +                std::getline(in, key, '=');
> +                std::getline(in, value, '=');
> +
> +                std::size_t pos = key.find(provider);
> +                if (pos == std::string::npos)
> +                    return;
> +                static const std::string option_marker{"--"};
> +                static const std::string scope_separator{"::"};
> +                key = key.erase(key.find_first_of(option_marker), option_marker.size());
> +                key = key.erase(key.find_first_of(provider), provider.size());
> +                key = key.erase(key.find_first_of(scope_separator), scope_separator.size());
> +
> +                std::cout << "\t" << key << " -> " << value << std::endl;
> +
> +                result.provider_options[provider].put(key, value);
> +            });
> +        }
> +    }
> +
> +    return result;
> +}
> +
> +void location::service::Daemon::print_help(std::ostream& out)
> +{
> +    mutable_daemon_options().print_help(out);
> +}
> +
> +int location::service::Daemon::main(const location::service::Daemon::Configuration& config)
> +{
> +    auto trap = core::posix::trap_signals_for_all_subsequent_threads(
> +    {
> +        core::posix::Signal::sig_term,
> +        core::posix::Signal::sig_int
> +    });
> +
> +    trap->signal_raised().connect([trap](const core::posix::Signal&)
> +    {
> +        trap->stop();
> +    });
> +
> +    const location::Configuration empty_provider_configuration;
> +
> +    std::set<location::Provider::Ptr> instantiated_providers;
> +
> +    for (const std::string& provider : config.providers)
> +    {
> +        std::cout << "Instantiating and configuring: " << provider << std::endl;
> +
> +        try
> +        {
> +            auto p = location::ProviderFactory::instance().create_provider_for_name_with_config(
> +                        provider,
> +                        config.provider_options.count(provider) > 0 ?
> +                            config.provider_options.at(provider) : empty_provider_configuration);
> +
> +            if (p)
> +                instantiated_providers.insert(p);
> +            else
> +                throw std::runtime_error("Problem instantiating provider");
> +
> +        } catch(const std::runtime_error& e)
> +        {
> +            std::cerr << "Exception instantiating provider: " << e.what() << " ... Aborting now." << std::endl;
> +            return EXIT_FAILURE;
> +        }
> +    }
> +
> +    config.incoming->install_executor(dbus::asio::make_executor(config.incoming));
> +    config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing));
> +
> +    location::service::DefaultConfiguration dc;
> +    location::service::Implementation::Configuration configuration
> +    {
> +        config.incoming,
> +        config.outgoing,
> +        dc.the_engine(instantiated_providers, dc.the_provider_selection_policy()),
> +        dc.the_permission_manager(),
> +        location::service::Harvester::Configuration
> +        {
> +            location::connectivity::platform_default_manager(),
> +            std::make_shared<NullReporter>()
> +        }
> +    };
> +
> +    location::service::Implementation location_service
> +    {
> +        configuration
> +    };
> +
> +    std::thread t1{[&config](){config.incoming->run();}};
> +    std::thread t2{[&config](){config.outgoing->run();}};
> +
> +    trap->run();
> +
> +    config.incoming->stop();
> +    config.outgoing->stop();
> +
> +    if (t1.joinable())
> +        t1.join();
> +
> +    if (t2.joinable())
> +        t2.join();
> +
> +    return EXIT_SUCCESS;
> +}
> +
> +namespace
> +{
> +location::ProgramOptions init_cli_options()
> +{
> +    location::ProgramOptions options;
> +
> +    options.add("help", "Produces this help message");
> +    options.add("property",
> +                "Property to set/get from a running service, known properties are:\n"
> +                "   is_online [get/set]\n"
> +                "   does_satellite_based_positioning [get/set]\n"
> +                "   does_report_wifi_and_cell_ids [get/set]\n"
> +                "   visible_space_vehicles [get]",
> +                location::service::Daemon::Cli::Property::unknown);
> +    options.add<std::string>("set", "Adjust the value of the property.");
> +    options.add("get", "Query the value of the property.");
> +
> +    return options;
> +}
> +
> +location::ProgramOptions& mutable_cli_options()
> +{
> +    static location::ProgramOptions options = init_cli_options();
> +    return options;
> +}
> +}
> +
> +location::service::Daemon::Cli::Configuration location::service::Daemon::Cli::Configuration::from_command_line_args(
> +        int argc,
> +        char** argv,
> +        location::service::Daemon::DBusConnectionFactory factory)
> +{
> +    location::service::Daemon::Cli::Configuration result;
> +
> +    if (!mutable_cli_options().parse_from_command_line_args(argc, (const char**)argv))
> +    {
> +        throw std::runtime_error{"Error parsing command line"};
> +    }
> +
> +    if (mutable_cli_options().value_count_for_key("help") > 0)
> +    {
> +        throw std::runtime_error{"Error parsing command line"};
> +    }
> +
> +    if (mutable_cli_options().value_count_for_key("get") > 0 && mutable_cli_options().value_count_for_key("set") > 0)
> +    {
> +        throw std::logic_error
> +        {
> +            "Both set and get specified, aborting..."
> +        };
> +    }
> +
> +    result.bus = factory(mutable_cli_options().bus());
> +
> +    result.property = mutable_cli_options().value_for_key<location::service::Daemon::Cli::Property>("property");
> +
> +    if (mutable_cli_options().value_count_for_key("get") > 0)
> +    {
> +        result.command = Command::get;
> +    }
> +    else if (mutable_cli_options().value_count_for_key("set") > 0)
> +    {
> +        result.command = Command::set;
> +        result.new_value = mutable_cli_options().value_for_key<std::string>("set");
> +    }
> +
> +    return result;
> +}
> +
> +/** @brief Pretty-prints the CLI's help text to the given output stream. */
> +void location::service::Daemon::Cli::print_help(std::ostream& out)
> +{
> +    mutable_cli_options().print_help(out);
> +}
> +
> +int location::service::Daemon::Cli::main(const location::service::Daemon::Cli::Configuration& config)
> +{
> +    auto location_service =
> +            dbus::resolve_service_on_bus<location::service::Interface, location::service::Stub>(config.bus);
> +
> +    switch (config.property)
> +    {
> +    case Property::is_online:
> +        switch (config.command)
> +        {
> +        case Command::get:
> +            std::cout << std::boolalpha << "Location service is "
> +                      << (location_service->is_online() ? "online" : "offline") << std::endl;
> +            break;
> +        case Command::set:
> +        {
> +            std::stringstream ss(config.new_value);
> +            bool flag = location_service->is_online();
> +            ss >> std::boolalpha >> flag;
> +
> +            std::cout << "Adjusting is_online property to value: " << config.new_value << " -> ";
> +
> +            location_service->is_online() = flag;
> +
> +            if (location_service->is_online() != flag)
> +            {
> +                std::cout << "failed" << std::endl;
> +                return EXIT_FAILURE;
> +            }
> +            std::cout << "succeeded" << std::endl;
> +            break;
> +        }
> +        case Command::unknown: break;
> +        }
> +        break;
> +    case Property::does_report_wifi_and_cell_ids:
> +        switch (config.command)
> +        {
> +        case Command::get:
> +            std::cout << std::boolalpha << "Location service "
> +                      << (location_service->does_report_cell_and_wifi_ids() ? "does" : "does not")
> +                      << " report cell and wifi ids." << std::endl;
> +            break;
> +        case Command::set:
> +        {
> +            std::stringstream ss(config.new_value);
> +            bool flag = location_service->does_report_cell_and_wifi_ids();
> +            ss >> std::boolalpha >> flag;
> +
> +            std::cout << "Adjusting does_report_cell_and_wifi_ids property to value: "
> +                      << std::boolalpha << flag << " -> ";
> +            location_service->does_report_cell_and_wifi_ids() = flag;
> +            if (location_service->does_report_cell_and_wifi_ids() != flag)
> +            {
> +                std::cout << "failed" << std::endl;
> +                return EXIT_FAILURE;
> +            }
> +            std::cout << "succeeded" << std::endl;
> +            break;
> +        }
> +        case Command::unknown: break;
> +        }
> +        break;
> +    case Property::does_satellite_based_positioning:
> +        switch (config.command)
> +        {
> +        case Command::get:
> +            std::cout << std::boolalpha << "Location service "
> +                      << (location_service->does_satellite_based_positioning() ? "does" : "does not")
> +                      << " satellite based positioning." << std::endl;
> +            break;
> +        case Command::set:
> +        {
> +            std::stringstream ss(config.new_value);
> +            bool flag = location_service->does_satellite_based_positioning();
> +            ss >> std::boolalpha >> flag;
> +
> +            std::cout << "Adjusting does_satellite_based_positioning property to value: "
> +                      << std::boolalpha << flag << " -> ";
> +            location_service->does_satellite_based_positioning() = flag;
> +            if (location_service->does_satellite_based_positioning() != flag)
> +            {
> +                std::cout << "failed" << std::endl;
> +                return EXIT_FAILURE;
> +            }
> +            std::cout << "succeeded" << std::endl;
> +            break;
> +        }
> +        case Command::unknown: break;
> +        }
> +        break;
> +    case Property::visible_space_vehicles:
> +    {
> +        switch (config.command)
> +        {
> +        case Command::get:
> +        {
> +            auto svs = location_service->visible_space_vehicles().get();
> +            std::cout << "Visible space vehicles:" << std::endl;
> +            for (const auto& sv : svs)
> +                std::cout << "\t" << sv.second << std::endl;
> +            break;
> +        }
> +        case Command::set:
> +            std::cout << "Property visible_space_vehicles is not set-able, aborting now." << std::endl;
> +            location::service::Daemon::Cli::print_help(std::cout);
> +            return EXIT_FAILURE;
> +        case Command::unknown: break;
> +        }
> +        break;
> +    }
> +    case Property::unknown:
> +        std::cout << "Unknown property, aborting now." << std::endl;
> +        location::service::Daemon::Cli::print_help(std::cout);
> +        return EXIT_FAILURE;
> +    }
> +
> +    return EXIT_SUCCESS;
> +}
> +
> +/** @brief Parses a Cli property from the given input stream, throws std::runtime_error. */
> +std::istream& location::service::operator>>(std::istream& in, location::service::Daemon::Cli::Property& property)
> +{
> +    static const std::map<std::string, location::service::Daemon::Cli::Property> lut =
> +    {
> +        {"is_online", location::service::Daemon::Cli::Property::is_online},
> +        {"does_satellite_based_positioning", location::service::Daemon::Cli::Property::does_satellite_based_positioning},
> +        {"does_report_wifi_and_cell_ids", location::service::Daemon::Cli::Property::does_report_wifi_and_cell_ids},
> +        {"visible_space_vehicles", location::service::Daemon::Cli::Property::visible_space_vehicles}
> +    };
> +
> +    std::string value; in >> value;
> +
> +    auto it = lut.find(value);
> +
> +    if (it == lut.end()) throw std::runtime_error
> +    {
> +        "Unknown property specified: " + value
> +    };
> +
> +    property = it->second;
> +    return in;
> +}
> +
> +/** @brief Parses a Cli property from the given input stream, throws std::runtime_error. */
> +std::ostream& location::service::operator<<(std::ostream& out, location::service::Daemon::Cli::Property property)
> +{
> +    switch (property)
> +    {
> +    case location::service::Daemon::Cli::Property::is_online:
> +        out << "is_online"; break;
> +    case location::service::Daemon::Cli::Property::does_satellite_based_positioning:
> +        out << "does_satellite_based_positioning"; break;
> +    case location::service::Daemon::Cli::Property::does_report_wifi_and_cell_ids:
> +        out << "does_report_wifi_and_cell_ids"; break;
> +    case location::service::Daemon::Cli::Property::visible_space_vehicles:
> +        out << "visible_space_vehicles"; break;
> +    case location::service::Daemon::Cli::Property::unknown:
> +        out << "unknown"; break;
> +    }
> +
> +    return out;
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/service/daemon.h'
> --- src/location_service/com/ubuntu/location/service/daemon.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/daemon.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,191 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DAEMON_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DAEMON_H_
> +
> +#include <com/ubuntu/location/configuration.h>
> +
> +#include <core/dbus/bus.h>
> +
> +#include <iosfwd>
> +#include <string>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +namespace service
> +{
> +/**
> + * @brief The Daemon struct encapsulates main functions for the location service and its cli.
> + */
> +struct Daemon
> +{
> +    /** @brief Function signature for creating DBus connections. */
> +    typedef std::function<core::dbus::Bus::Ptr(core::dbus::WellKnownBus)> DBusConnectionFactory;
> +
> +    /** @brief Returns the default connection factory. */
> +    static DBusConnectionFactory default_dbus_connection_factory()
> +    {
> +        return [](core::dbus::WellKnownBus bus)
> +        {
> +            return core::dbus::Bus::Ptr
> +            {
> +                new core::dbus::Bus(bus)
> +            };
> +        };
> +    }
> +
> +    /** @brief Describes the command-line interface to the daemon. */
> +    struct Cli
> +    {
> +        Cli() = delete;
> +
> +        /** @brief Enumerates all commands known to the cli. */
> +        enum class Command
> +        {
> +            /** @brief Marks the unknown command. */
> +            unknown,
> +            /** @brief Request to query a property value of the running service. */
> +            get,
> +            /** @brief Request to adjust a property value of the running service. */
> +            set
> +        };
> +
> +        /** @brief Enumerates all properties known to the cli. */
> +        enum class Property
> +        {
> +            /** @brief Marks the unknown property. */
> +            unknown,
> +            /** @brief Indicates whether the positioning engine is online. */
> +            is_online,
> +            /** @brief Indicates whether the positioning engine uses satellite-based positioning. */
> +            does_satellite_based_positioning,
> +            /** @brief Indicates whether the positioning engine leverages wifi and cell ids for positioning. */
> +            does_report_wifi_and_cell_ids,
> +            /** @brief The list of currently visible space-vehicles. */
> +            visible_space_vehicles
> +        };
> +
> +        /** @brief Parameters for an invocation of the CLI. */
> +        struct Configuration
> +        {
> +            /** @brief Parses a configuration from the command line.
> +             *
> +             * --bus arg (=session)      The well-known bus to connect to the service upon
> +             * --help                    Produces this help message
> +             * --property arg (=unknown) Property to set/get from a running service, known
> +                                         properties are:
> +                                            is_online [get/set]
> +                                            does_satellite_based_positioning [get/set]
> +                                            does_report_wifi_and_cell_ids [get/set]
> +                                            visible_space_vehicles [get]
> +             * --set arg                 Adjust the value of the property.
> +             * --get                     Query the value of the property.
> +             */
> +            static Configuration from_command_line_args(
> +                    int argc,
> +                    char** argv,
> +                    DBusConnectionFactory factory = default_dbus_connection_factory());
> +
> +            /** @brief The bus to connect to. */
> +            core::dbus::Bus::Ptr bus;
> +
> +            /** @brief The command to execute against a running daemon. */
> +            Command command
> +            {
> +                Command::unknown
> +            };
> +
> +            /** @brief If command is get/set/monitor, the property to act upon. */
> +            Property property
> +            {
> +                Property::unknown
> +            };
> +
> +            /** @brief The new, string-based value for a property. */
> +            std::string new_value;
> +        };
> +
> +        /** @brief Pretty-prints the CLI's help text to the given output stream. */
> +        static void print_help(std::ostream& out);
> +
> +        /**
> +         * @brief main of the command-line interface to the location service.
> +         * @return EXIT_SUCCESS or EXIT_FAILURE.
> +         */
> +        static int main(const Configuration& configuration);
> +    };
> +
> +    Daemon() = delete;
> +
> +    /** @brief Parameters for an invocation of the daemon. */
> +    struct Configuration
> +    {
> +        /** @brief Parses a configuration from the command line.
> +         *
> +         *   --bus arg (=session)  The well-known bus to connect to the service upon
> +         *   --help                Produces this help message
> +         *   --testing             Enables executing the service without selected providers
> +         *   --provider arg        The providers that should be added to the engine
> +         */
> +        static Configuration from_command_line_args(
> +                int argc,
> +                char** argv,
> +                DBusConnectionFactory factory = default_dbus_connection_factory());
> +
> +        /** @brief The bus to expose the service upon. */
> +        core::dbus::Bus::Ptr incoming;
> +
> +        /** @brief The bus to use for querying other services. */
> +        core::dbus::Bus::Ptr outgoing;
> +
> +        /** @brief Configures the daemon for testing mode. */
> +        bool is_testing_enabled
> +        {
> +            false
> +        };
> +        /** @brief Providers that have been requested on the command line. */
> +        std::vector<std::string> providers;
> +        /** @brief Provider-specific options keyed on the provider name. */
> +        std::map< std::string, location::Configuration > provider_options;
> +    };
> +
> +    /** @brief Pretty-prints the CLI's help text to the given output stream. */
> +    static void print_help(std::ostream& out);
> +
> +    /**
> +     * @brief Executes the daemon with the given configuration.
> +     * @return EXIT_SUCCESS or EXIT_FAILURE.
> +     */
> +    static int main(const Configuration& config);
> +};
> +
> +/** @brief Parses a Cli property from the given input stream, throws std::runtime_error. */
> +std::istream& operator>>(std::istream& in, Daemon::Cli::Property& property);
> +
> +/** @brief Pretty-prints a property value */
> +std::ostream& operator<<(std::ostream& out, Daemon::Cli::Property property);
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DAEMON_H_
> 
> === added file 'src/location_service/com/ubuntu/location/service/daemon_cli_main.cpp'
> --- src/location_service/com/ubuntu/location/service/daemon_cli_main.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/daemon_cli_main.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include "daemon.h"
> +
> +#include <iostream>
> +#include <stdexcept>
> +
> +namespace location = com::ubuntu::location;
> +
> +int main(int argc, char** argv)
> +{
> +    location::service::Daemon::Cli::Configuration config;
> +    try
> +    {
> +        config = location::service::Daemon::Cli::Configuration::from_command_line_args(argc, argv);
> +    } catch(const std::runtime_error& e)
> +    {
> +        std::cout << "Problem parsing command line: " << e.what() << std::endl;
> +        location::service::Daemon::Cli::print_help(std::cout);
> +        return EXIT_FAILURE;
> +    }
> +
> +    try
> +    {
> +        location::service::Daemon::Cli::main(config);
> +    } catch(const std::exception& e)
> +    {
> +        std::cout << "Problem executing the CLI: " << e.what() << std::endl;
> +        return EXIT_FAILURE;
> +    }
> +
> +    return EXIT_SUCCESS;
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/service/daemon_main.cpp'
> --- src/location_service/com/ubuntu/location/service/daemon_main.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/daemon_main.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,46 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include "daemon.h"
> +
> +namespace location = com::ubuntu::location;
> +
> +int main(int argc, char** argv)
> +{
> +    location::service::Daemon::Configuration config;
> +    try
> +    {
> +        config = location::service::Daemon::Configuration::from_command_line_args(argc, argv);
> +    } catch(const std::runtime_error& e)
> +    {
> +        std::cerr << "Problem parsing command line: " << e.what();
> +        location::service::Daemon::print_help(std::cerr);
> +        return EXIT_FAILURE;
> +    }
> +
> +    try
> +    {
> +        location::service::Daemon::main(config);
> +    } catch(const std::exception& e)
> +    {
> +        std::cout << "Problem executing the daemon: " << e.what() << std::endl;
> +        return EXIT_FAILURE;
> +    }
> +
> +    return EXIT_SUCCESS;
> +}
> 
> === modified file 'src/location_service/com/ubuntu/location/service/default_configuration.cpp'
> --- src/location_service/com/ubuntu/location/service/default_configuration.cpp	2013-05-30 10:21:26 +0000
> +++ src/location_service/com/ubuntu/location/service/default_configuration.cpp	2014-06-24 16:02:38 +0000
> @@ -15,10 +15,10 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/service/default_configuration.h"
> -#include "com/ubuntu/location/service/default_permission_manager.h"
> +#include <com/ubuntu/location/service/default_configuration.h>
> +#include <com/ubuntu/location/service/default_permission_manager.h>
>  
> -#include "com/ubuntu/location/default_provider_selection_policy.h"
> +#include <com/ubuntu/location/default_provider_selection_policy.h>
>  
>  namespace cul = com::ubuntu::location;
>  namespace culs = com::ubuntu::location::service;
> @@ -35,7 +35,11 @@
>      const std::set<cul::Provider::Ptr>& provider_set,
>      const cul::ProviderSelectionPolicy::Ptr& provider_selection_policy)
>  {
> -    return Engine::Ptr {new Engine{provider_set, provider_selection_policy}};
> +    auto engine = std::make_shared<cul::Engine>(provider_selection_policy);
> +    for (const auto& provider : provider_set)
> +        engine->add_provider(provider);
> +
> +    return engine;
>  }
>  
>  cul::ProviderSelectionPolicy::Ptr culs::DefaultConfiguration::the_provider_selection_policy()
> 
> === modified file 'src/location_service/com/ubuntu/location/service/default_permission_manager.cpp'
> --- src/location_service/com/ubuntu/location/service/default_permission_manager.cpp	2013-05-28 14:41:06 +0000
> +++ src/location_service/com/ubuntu/location/service/default_permission_manager.cpp	2014-06-24 16:02:38 +0000
> @@ -15,7 +15,9 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/service/default_permission_manager.h"
> +#include <com/ubuntu/location/service/default_permission_manager.h>
> +
> +#include <iostream>
>  
>  namespace cul = com::ubuntu::location;
>  namespace culs = com::ubuntu::location::service;
> 
> === added file 'src/location_service/com/ubuntu/location/service/harvester.cpp'
> --- src/location_service/com/ubuntu/location/service/harvester.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/harvester.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,79 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include <com/ubuntu/location/service/harvester.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +
> +namespace location = com::ubuntu::location;
> +
> +location::service::Harvester::Harvester(const location::service::Harvester::Configuration& configuration)
> +    : config(configuration),
> +      is_running{false}
> +{
> +}
> +
> +location::service::Harvester::~Harvester()
> +{
> +    stop();
> +}
> +
> +/** @brief Report updated position to the harvester instance. */
> +void location::service::Harvester::report_position_update(const location::Update<location::Position>& update)
> +{
> +    VLOG(10) << "Reference location changed: " << update;
> +
> +    if (not is_running.load())
> +        return;
> +
> +    std::vector<location::connectivity::WirelessNetwork::Ptr> visible_wifis;
> +    config.connectivity_manager->enumerate_visible_wireless_networks([&visible_wifis](location::connectivity::WirelessNetwork::Ptr wifi)
> +    {
> +        VLOG(10) << "Got a visible wifi: " << *wifi << std::endl;
> +        visible_wifis.push_back(wifi);
> +    });
> +
> +    std::vector<location::connectivity::RadioCell::Ptr> connected_cells;
> +    config.connectivity_manager->enumerate_connected_radio_cells([&connected_cells](location::connectivity::RadioCell::Ptr cell)
> +    {
> +        VLOG(10) << "Got a cell: " << *cell << std::endl;
> +        connected_cells.push_back(cell);
> +    });
> +
> +    config.reporter->report(update, visible_wifis, connected_cells);
> +}
> +
> +void location::service::Harvester::start()
> +{
> +    if (is_running.load())
> +        return;
> +
> +    is_running.exchange(true);
> +
> +    config.reporter->start();
> +}
> +
> +void location::service::Harvester::stop()
> +{
> +    if (not is_running.load())
> +        return;
> +
> +    is_running.exchange(false);
> +
> +    config.reporter->stop();
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/service/harvester.h'
> --- src/location_service/com/ubuntu/location/service/harvester.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/harvester.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_HARVESTER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_HARVESTER_H_
> +
> +#include <com/ubuntu/location/engine.h>
> +#include <com/ubuntu/location/update.h>
> +#include <com/ubuntu/location/connectivity/manager.h>
> +
> +namespace com
> +{
> +namespace ubuntu
> +{
> +namespace location
> +{
> +namespace service
> +{
> +/** @brief Models a wifi- and cell-id harvester for crowd-sourcing purposes. */
> +class Harvester
> +{
> +public:
> +
> +    /** @brief Models a reporter of position updates, augmented with wifi and cell ids. */
> +    struct Reporter
> +    {
> +        /** @cond */
> +        typedef std::shared_ptr<Reporter> Ptr;
> +
> +        Reporter() = default;
> +        virtual ~Reporter() = default;
> +        /** @endcond */
> +
> +        /** @brief Tell the reporter that it should start operating. */
> +        virtual void start() = 0;
> +
> +        /** @brief Tell the reporter to shut down its operation. */
> +        virtual void stop() = 0;
> +
> +        /**
> +         * @brief Triggers the reporter to send off the information.
> +         */
> +        virtual void report(const Update<Position>& update,
> +                            const std::vector<connectivity::WirelessNetwork::Ptr>& wifis,
> +                            const std::vector<connectivity::RadioCell::Ptr>& cells) = 0;
> +    };
> +
> +    /** @brief Configuration encapsulates all creation time options of class Harvester */
> +    struct Configuration
> +    {
> +        /** The connectivity manager that the harvester should use. */
> +        std::shared_ptr<connectivity::Manager> connectivity_manager;
> +        /** The reporter implementation */
> +        std::shared_ptr<Reporter> reporter;
> +    };
> +
> +    /** @brief Creates a new instance and wires up to system components for receiving
> +     *  location updates, and wifi and cell id measurements.
> +     */
> +    Harvester(const Configuration& configuration);
> +
> +    /** @brief Stops the data collection and frees all resources held by the instance. */
> +    virtual ~Harvester();
> +
> +    /** @brief Report updated position to the harvester instance. */
> +    virtual void report_position_update(const Update<Position>& update);
> +
> +    /** @brief Starts the harvester instance and its data collection. */
> +    virtual void start();
> +
> +    /** @brief Stops the harvester instance and its data collection. */
> +    virtual void stop();
> +
> +private:
> +    Configuration config;
> +    std::atomic<bool> is_running;
> +};
> +}
> +}
> +}
> +}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_HARVESTER_H_
> 
> === added file 'src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp'
> --- src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/ichnaea_reporter.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,226 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include <com/ubuntu/location/service/ichnaea_reporter.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +
> +#include <core/net/http/client.h>
> +#include <core/net/http/content_type.h>
> +#include <core/net/http/request.h>
> +#include <core/net/http/response.h>
> +#include <core/net/http/status.h>
> +
> +#include <json/json.h>
> +
> +#include <thread>
> +
> +namespace json = Json;
> +namespace location = com::ubuntu::location;
> +
> +location::service::ichnaea::Reporter::Reporter(
> +        const location::service::ichnaea::Reporter::Configuration& configuration)
> +    : http_client(core::net::http::make_client())
> +{
> +    auto uri = configuration.uri +
> +            ichnaea::submit::resource +
> +            configuration.key;
> +
> +    submit_request_config = core::net::http::Request::Configuration::from_uri_as_string(uri);
> +    submit_request_config.ssl.verify_host = false;
> +    submit_request_config.ssl.verify_peer = false;
> +
> +    if (not configuration.nick_name.empty())
> +        submit_request_config.header.add(Reporter::nick_name_header, configuration.nick_name);
> +}
> +
> +location::service::ichnaea::Reporter::~Reporter()
> +{
> +    stop();
> +}
> +
> +void location::service::ichnaea::Reporter::start()
> +{
> +    http_client_worker = std::move(
> +                std::thread
> +                {
> +                    [this]()
> +                    {
> +                        http_client->run();
> +                    }
> +                });
> +}
> +
> +void location::service::ichnaea::Reporter::stop()
> +{
> +    http_client->stop();
> +
> +    if (http_client_worker.joinable())
> +        http_client_worker.join();
> +}
> +
> +void location::service::ichnaea::Reporter::report(
> +        const location::Update<location::Position>& update,
> +        const std::vector<location::connectivity::WirelessNetwork::Ptr>& wifis,
> +        const std::vector<location::connectivity::RadioCell::Ptr>& cells)
> +{
> +    json::Value submit;
> +    json::Value item;
> +
> +    item[Json::radio] = "gsm"; // We currently only support gsm radio types.
> +    item[Json::lat] = update.value.latitude.value.value();
> +    item[Json::lon] = update.value.longitude.value.value();
> +
> +    if (update.value.accuracy.horizontal)
> +        item[Json::accuracy] = (*update.value.accuracy.horizontal).value();
> +    if (update.value.altitude)
> +        item[Json::altitude] = (*update.value.altitude).value.value();
> +    if (update.value.accuracy.vertical)
> +        item[Json::altitude_accuracy] = (*update.value.accuracy.vertical).value();
> +
> +    if (!wifis.empty())
> +        ichnaea::Reporter::convert_wifis_to_json(wifis, item[Json::wifi]);
> +
> +    if (!cells.empty())
> +        ichnaea::Reporter::convert_cells_to_json(cells, item[Json::cell]);
> +
> +    submit[Json::items].append(item);
> +
> +    json::FastWriter writer;
> +
> +    VLOG(10) << "Submitting: " << writer.write(submit);
> +
> +    auto request = http_client->post(
> +                submit_request_config,
> +                writer.write(submit),
> +                core::net::http::ContentType::json);
> +
> +    request->async_execute(
> +                core::net::http::Request::Handler()
> +                .on_response([](const core::net::http::Response& response)
> +                {
> +                    if (response.status != ichnaea::submit::success)
> +                        LOG(ERROR) << "Error submitting to ichnaea: " << response.body;
> +                    else
> +                        LOG(INFO) << "Succesfully submitted to ichnaea.";
> +                })
> +                .on_error([](const core::net::Error& e)
> +                {
> +                    LOG(ERROR) << "Networking error while submitting to ichnaea: " << e.what();
> +                }));
> +}
> +
> +void location::service::ichnaea::Reporter::convert_wifis_to_json(
> +        const std::vector<location::connectivity::WirelessNetwork::Ptr>& wifis,
> +        json::Value& destination)
> +{
> +    for (const auto& wifi : wifis)
> +    {
> +        // We do not harvest any Wifi marked with '_nomap'.
> +        if (wifi->ssid().get().find("_nomap") != std::string::npos)
> +            continue;
> +
> +        json::Value w;
> +        w[Json::Wifi::key] = wifi->bssid().get();
> +
> +        if (wifi->frequency().get().is_valid())
> +            w[Json::Wifi::frequency] = static_cast<int>(wifi->frequency().get());
> +
> +        // We have a relative signal strength percentage in the wifi record.
> +        // TODO(tvoss): Check how that could be translated to RSSI.
> +        //wifi[Json::Wifi::signal] = -50;
> +
> +        destination.append(w);
> +    }
> +}
> +
> +void location::service::ichnaea::Reporter::convert_cells_to_json(
> +        const std::vector<location::connectivity::RadioCell::Ptr>& cells,
> +        json::Value& destination)
> +{
> +    for (const auto& cell : cells)
> +    {
> +        json::Value c;
> +
> +        switch (cell->type())
> +        {
> +        case connectivity::RadioCell::Type::gsm:
> +        {
> +            c[Json::Cell::radio] = "gsm";
> +
> +            const auto& details = cell->gsm();
> +
> +            if (details.mobile_country_code.is_valid())
> +                c[Json::Cell::mcc] = details.mobile_country_code.get();
> +            if (details.mobile_network_code.is_valid())
> +                c[Json::Cell::mnc] = details.mobile_network_code.get();
> +            if (details.location_area_code.is_valid())
> +                c[Json::Cell::lac] = details.location_area_code.get();
> +            if (details.id.is_valid())
> +                c[Json::Cell::cid] = details.id.get();
> +            if  (details.strength.is_valid())
> +                c[Json::Cell::asu] = details.strength.get();
> +
> +            break;
> +        }
> +        case connectivity::RadioCell::Type::umts:
> +        {
> +            c[Json::Cell::radio] = "umts";
> +
> +            const auto& details = cell->umts();
> +
> +            if (details.mobile_country_code.is_valid())
> +                c[Json::Cell::mcc] = details.mobile_country_code.get();
> +            if (details.mobile_network_code.is_valid())
> +                c[Json::Cell::mnc] = details.mobile_network_code.get();
> +            if (details.location_area_code.is_valid())
> +                c[Json::Cell::lac] = details.location_area_code.get();
> +            if (details.id.is_valid())
> +                c[Json::Cell::cid] = details.id.get();
> +            if  (details.strength.is_valid())
> +                c[Json::Cell::asu] = details.strength.get();
> +
> +            break;
> +        }
> +        case connectivity::RadioCell::Type::lte:
> +        {
> +            c[Json::Cell::radio] = "lte";
> +
> +            const auto& details = cell->lte();
> +
> +            if (details.mobile_country_code.is_valid())
> +                c[Json::Cell::mcc] = details.mobile_country_code.get();
> +            if (details.mobile_network_code.is_valid())
> +                c[Json::Cell::mnc] = details.mobile_network_code.get();
> +            if (details.tracking_area_code.is_valid())
> +                c[Json::Cell::lac] = details.tracking_area_code.get();
> +            if (details.id.is_valid())
> +                c[Json::Cell::cid] = details.id.get();
> +            if (details.physical_id.is_valid())
> +                c[Json::Cell::psc] = details.physical_id.get();
> +            if  (details.strength.is_valid())
> +                c[Json::Cell::asu] = details.strength.get();
> +            break;
> +        }
> +        default:
> +            break;
> +        }
> +
> +        destination.append(c);
> +    }
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/service/ichnaea_reporter.h'
> --- src/location_service/com/ubuntu/location/service/ichnaea_reporter.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/ichnaea_reporter.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,155 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_ICHNAEA_REPORTER_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_ICHNAEA_REPORTER_H_
> +
> +#include <com/ubuntu/location/service/harvester.h>
> +
> +#include <core/net/http/client.h>
> +#include <core/net/http/content_type.h>
> +#include <core/net/http/request.h>
> +#include <core/net/http/response.h>
> +#include <core/net/http/status.h>
> +
> +#include <json/json.h>
> +
> +#include <thread>
> +
> +namespace json = Json;
> +
> +namespace com{namespace ubuntu{namespace location{namespace service
> +{
> +/**
> + * @brief All types and functions that are used to communicate with instances
> + * of the Mozilla location service go here. Please see for further details:
> + *
> + *   - https://mozilla-ichnaea.readthedocs.org/en/latest/api/index.html#submit
> + *   - https://github.com/mozilla/MozStumbler
> + */
> +namespace ichnaea
> +{
> +namespace submit
> +{
> +/** @brief Resource path for wifi- and cell-id submissions.  */
> +constexpr const char* resource
> +{
> +    "/v1/submit?key="
> +};
> +/** @brief Http code marking errors for Mozilla location service instances. */
> +const core::net::http::Status error
> +{
> +    core::net::http::Status::bad_request
> +};
> +/** @brief Http code marking a successful submission request to Mozilla location service instances. */
> +const core::net::http::Status success
> +{
> +    core::net::http::Status::no_content
> +};
> +}
> +
> +struct Reporter : public Harvester::Reporter
> +{
> +    /** @brief Submissions can be tagged with a nick-name for tracking on leaderboards. */
> +    static constexpr const char* nick_name_header{"X-Nickname"};
> +
> +    /** @brief The JSON-dialect of the Mozilla location service is described here. */
> +    struct Json
> +    {
> +        static constexpr const char* radio{"radio"};
> +        static constexpr const char* lat{"lat"};
> +        static constexpr const char* lon{"lon"};
> +        static constexpr const char* accuracy{"accuracy"};
> +        static constexpr const char* altitude{"altitude"};
> +        static constexpr const char* altitude_accuracy{"altitude_accuracy"};
> +
> +        static constexpr const char* items{"items"};
> +
> +        static constexpr const char* cell{"cell"};
> +        static constexpr const char* wifi{"wifi"};
> +
> +        struct Cell
> +        {
> +            static constexpr const char* radio{"radio"};
> +            static constexpr const char* mcc{"mcc"};
> +            static constexpr const char* mnc{"mnc"};
> +            static constexpr const char* lac{"lac"};
> +            static constexpr const char* cid{"cid"};
> +            static constexpr const char* psc{"psc"};
> +            static constexpr const char* asu{"asu"};
> +        };
> +
> +        struct Wifi
> +        {
> +            static constexpr const char* channel{"channel"};
> +            static constexpr const char* frequency{"frequency"};
> +            static constexpr const char* key{"key"};
> +            static constexpr const char* signal{"signal"};
> +        };
> +    };
> +
> +    /** Creation-time options for the ICHNAEA reporter */
> +    struct Configuration
> +    {
> +        /** Uri of the ICHNAEA instance we want to submit to. */
> +        std::string uri;
> +        /** API key for the submission */
> +        std::string key;
> +        /** Nickname for the submission */
> +        std::string nick_name;
> +    };
> +
> +    /** @brief Constructs a new instance with the given parameters. */
> +    Reporter(const Configuration& configuration);
> +    /** @brief Stops the reporter instance and frees all related resources. */
> +    ~Reporter();
> +
> +    /** @brief Starts the reporter and prepares for submission. */
> +    void start() override;    
> +    /** @brief Stops the reporter. */
> +    void stop() override;
> +
> +    /**
> +     * @brief Announced a position update, together with visible wifis and cells to the reporter.
> +     * @throws std::runtime_error if wifis and cells are empty.
> +     */
> +    void report(
> +            const Update<Position>& update,
> +            const std::vector<connectivity::WirelessNetwork::Ptr>& wifis,
> +            const std::vector<connectivity::RadioCell::Ptr>& cells) override;
> +
> +    /** @brief Encodes a collection of wifis into the Mozilla loation service JSON dialect. */
> +    static void convert_wifis_to_json(
> +            const std::vector<connectivity::WirelessNetwork::Ptr>& wifis,
> +            json::Value& destination);
> +
> +    /** @brief Encodes a collection of radio cells into the Mozilla loation service JSON dialect. */
> +    static void convert_cells_to_json(
> +            const std::vector<connectivity::RadioCell::Ptr>& cells,
> +            json::Value& destination);
> +
> +    /** @brief The http request configuration for submissions to the mozilla location service. */
> +    core::net::http::Request::Configuration submit_request_config;
> +    /** @brief The http client instance used to talk to Mozilla location service instances. */
> +    std::shared_ptr<core::net::http::Client> http_client;
> +    /** @brief Worker thread for dispatching the http client instance. */
> +    std::thread http_client_worker;
> +};
> +}
> +}}}}
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_ICHNAEA_REPORTER_H_
> 
> === modified file 'src/location_service/com/ubuntu/location/service/implementation.cpp'
> --- src/location_service/com/ubuntu/location/service/implementation.cpp	2014-01-31 11:08:33 +0000
> +++ src/location_service/com/ubuntu/location/service/implementation.cpp	2014-06-24 16:02:38 +0000
> @@ -1,10 +1,31 @@
> -#include "com/ubuntu/location/service/implementation.h"
> -
> -#include "com/ubuntu/location/service/session/implementation.h"
> -
> -#include "com/ubuntu/location/criteria.h"
> -#include "com/ubuntu/location/engine.h"
> -#include "com/ubuntu/location/proxy_provider.h"
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#include <com/ubuntu/location/service/implementation.h>
> +
> +#include <com/ubuntu/location/connectivity/manager.h>
> +#include <com/ubuntu/location/service/harvester.h>
> +
> +#include <com/ubuntu/location/service/session/implementation.h>
> +
> +#include <com/ubuntu/location/criteria.h>
> +#include <com/ubuntu/location/engine.h>
> +#include <com/ubuntu/location/logging.h>
> +#include <com/ubuntu/location/proxy_provider.h>
>  
>  #include <core/dbus/bus.h>
>  #include <core/dbus/service.h>
> @@ -20,49 +41,110 @@
>  
>  namespace dbus = core::dbus;
>  
> -struct culs::Implementation::Private
> -{
> -    dbus::types::ObjectPath make_session_path()
> -    {
> -        static std::size_t counter{0};
> -        std::stringstream ss; ss << "/sessions/" << counter;
> -        counter++;
> -
> -        return dbus::types::ObjectPath{ss.str()};
> -    }
> -
> -    dbus::Bus::Ptr bus;
> -    cul::Engine::Ptr engine;
> -    culs::PermissionManager::Ptr permission_manager;
> -};
> -
> -culs::Implementation::Implementation(
> -    const dbus::Bus::Ptr& bus,
> -    const cul::Engine::Ptr& engine,
> -    const culs::PermissionManager::Ptr& permission_manager)
> -    : Skeleton(bus, permission_manager),
> -      d{new Private{bus, engine, permission_manager}}
> -{
> -    if (!bus)
> -        throw std::runtime_error("Cannot create service for null bus.");
> -    if (!engine)
> +culs::Implementation::Implementation(const culs::Implementation::Configuration& config)
> +    : Skeleton
> +      {
> +          Skeleton::Configuration
> +          {
> +              config.incoming,
> +              config.outgoing,
> +              culs::Skeleton::CredentialsResolver::Ptr
> +              {
> +                  new culs::Skeleton::DBusDaemonCredentialsResolver
> +                  {
> +                      config.outgoing
> +                  }
> +              },
> +              culs::Skeleton::ObjectPathGenerator::Ptr
> +              {
> +                  new culs::Skeleton::ObjectPathGenerator{}
> +              },
> +              config.permission_manager
> +          }
> +      },
> +      configuration(config),
> +      harvester(config.harvester),
> +      connections
> +      {
> +          is_online().changed().connect(
> +              [this](bool value)
> +              {
> +                  configuration.engine->configuration.engine_state
> +                        = value ?
> +                            Engine::Status::on :
> +                            Engine::Status::off;
> +              }),
> +          does_report_cell_and_wifi_ids().changed().connect(
> +              [this](bool value)
> +              {
> +                  configuration.engine->configuration.wifi_and_cell_id_reporting_state
> +                      = value ?
> +                          cul::WifiAndCellIdReportingState::on :
> +                          cul::WifiAndCellIdReportingState::off;
> +              }),
> +          does_satellite_based_positioning().changed().connect(
> +              [this](bool value)
> +              {
> +                  configuration.engine->configuration.satellite_based_positioning_state
> +                          = value ?
> +                              cul::SatelliteBasedPositioningState::on :
> +                              cul::SatelliteBasedPositioningState::off;
> +              }),
> +          configuration.engine->configuration.engine_state.changed().connect(
> +              [this](Engine::Status status)
> +              {
> +                  is_online() =
> +                          status == Engine::Status::on ||
> +                          status == Engine::Status::active;
> +              }),
> +          configuration.engine->configuration.satellite_based_positioning_state.changed().connect(
> +              [this](cul::SatelliteBasedPositioningState state)
> +              {
> +                  does_satellite_based_positioning() =
> +                          state == cul::SatelliteBasedPositioningState::on;
> +              }),
> +          configuration.engine->updates.visible_space_vehicles.changed().connect(
> +              [this](const std::map<cul::SpaceVehicle::Key, cul::SpaceVehicle>&svs)
> +              {
> +                  visible_space_vehicles() = svs;
> +              }),
> +          configuration.engine->updates.reference_location.changed().connect(
> +              [this](const cul::Update<cul::Position>& update)
> +              {
> +                  harvester.report_position_update(update);
> +              })
> +      }
> +{
> +    if (!configuration.incoming)
> +        throw std::runtime_error("Cannot create service for null bus.");
> +    if (!configuration.outgoing)
> +        throw std::runtime_error("Cannot create service for null bus.");
> +    if (!configuration.engine)
>          throw std::runtime_error("Cannot create service for null engine.");
> -    if (!permission_manager)
> +    if (!configuration.permission_manager)
>          throw std::runtime_error("Cannot create service for null permission manager.");
> -}
> -
> -culs::Implementation::~Implementation() noexcept
> -{
> +
> +    is_online() =
> +            configuration.engine->configuration.engine_state == Engine::Status::on ||
> +            configuration.engine->configuration.engine_state == Engine::Status::active;
> +    does_report_cell_and_wifi_ids() =
> +            configuration.engine->configuration.wifi_and_cell_id_reporting_state ==
> +            cul::WifiAndCellIdReportingState::on;
> +    does_satellite_based_positioning() =
> +            configuration.engine->configuration.satellite_based_positioning_state ==
> +            cul::SatelliteBasedPositioningState::on;
> +
> +    harvester.start();
>  }
>  
>  culs::session::Interface::Ptr culs::Implementation::create_session_for_criteria(const cul::Criteria& criteria)
>  {
>      auto provider_selection
> -            = d->engine->determine_provider_selection_for_criteria(criteria);
> +            = configuration.engine->determine_provider_selection_for_criteria(criteria);
>      auto proxy_provider = ProxyProvider::Ptr
> -            {
> -                new ProxyProvider{provider_selection}
> -            };
> -    
> -    return session::Interface::Ptr{new session::Implementation(d->bus, d->make_session_path(), proxy_provider)};
> +    {
> +        new ProxyProvider{provider_selection}
> +    };
> +
> +    return session::Interface::Ptr{new culs::session::Implementation(proxy_provider)};
>  }
> 
> === renamed file 'include/location_service/com/ubuntu/location/service/implementation.h' => 'src/location_service/com/ubuntu/location/service/implementation.h'
> --- include/location_service/com/ubuntu/location/service/implementation.h	2014-01-31 11:08:33 +0000
> +++ src/location_service/com/ubuntu/location/service/implementation.h	2014-06-24 16:02:38 +0000
> @@ -18,8 +18,10 @@
>  #ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_IMPLEMENTATION_H_
>  #define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_IMPLEMENTATION_H_
>  
> -#include "com/ubuntu/location/engine.h"
> -#include "com/ubuntu/location/service/skeleton.h"
> +#include <com/ubuntu/location/engine.h>
> +#include <com/ubuntu/location/connectivity/manager.h>
> +#include <com/ubuntu/location/service/harvester.h>
> +#include <com/ubuntu/location/service/skeleton.h>
>  
>  #include <memory>
>  
> @@ -35,22 +37,47 @@
>  {
>  class Implementation : public Skeleton
>  {
> -  public:
> +public:
>      typedef std::shared_ptr<Implementation> Ptr;
>  
> -    Implementation(
> -        const core::dbus::Bus::Ptr& bus,
> -        const Engine::Ptr& engine,
> -        const PermissionManager::Ptr& permission_manager);
> -    Implementation(const Implementation&) = delete;
> -    virtual ~Implementation() noexcept;
> -    Implementation& operator=(const Implementation&) = delete;
> -
> -    virtual session::Interface::Ptr create_session_for_criteria(const Criteria& criteria);
> +    // Summarizes configuration options for the implementation.
> +    struct Configuration
> +    {
> +        // The bus connection to expose the service upon.
> +        core::dbus::Bus::Ptr incoming;
> +        // The bus connection for querying other services.
> +        core::dbus::Bus::Ptr outgoing;
> +        // The positioning Engine that the service should use.
> +        Engine::Ptr engine;
> +        // The permission manager that the service should use.
> +        PermissionManager::Ptr permission_manager;
> +        // All harvesting specific options.
> +        Harvester::Configuration harvester;
> +    };
> +
> +    // Creates a new instance of the service with the given configuration.
> +    // Throws std::runtime_error in case of issues.
> +    Implementation(const Configuration& configuration);
> +
> +    // Creates a new session for the given criteria.
> +    session::Interface::Ptr create_session_for_criteria(const Criteria& criteria);
>  
>    private:
> -    struct Private;
> -    std::unique_ptr<Private> d;
> +    // The service configuration.
> +    Configuration configuration;
> +    // The harvester instance.
> +    Harvester harvester;
> +    // All event connections are automatically cut on destruction.
> +    struct
> +    {
> +        core::ScopedConnection is_online;
> +        core::ScopedConnection does_report_cell_and_wifi_ids;
> +        core::ScopedConnection does_satellite_based_positioning;
> +        core::ScopedConnection engine_state;
> +        core::ScopedConnection satellite_based_positioning_state;
> +        core::ScopedConnection visible_space_vehicles;
> +        core::ScopedConnection reference_position;
> +    } connections;
>  };
>  }
>  }
> 
> === removed file 'src/location_service/com/ubuntu/location/service/main.cpp'
> --- src/location_service/com/ubuntu/location/service/main.cpp	2014-01-31 11:08:33 +0000
> +++ src/location_service/com/ubuntu/location/service/main.cpp	1970-01-01 00:00:00 +0000
> @@ -1,148 +0,0 @@
> -/*
> - * Copyright © 2012-2013 Canonical Ltd.
> - *
> - * This program is free software: you can redistribute it and/or modify it
> - * under the terms of the GNU Lesser General Public License version 3,
> - * as published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public License
> - * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> - *
> - * Authored by: Thomas Voß <thomas.voss at canonical.com>
> - */
> -#include "program_options.h"
> -
> -#include "com/ubuntu/location/provider_factory.h"
> -
> -#include "com/ubuntu/location/service/default_configuration.h"
> -#include "com/ubuntu/location/service/implementation.h"
> -
> -#include <core/dbus/announcer.h>
> -#include <core/dbus/asio/executor.h>
> -
> -#include <thread>
> -
> -namespace cul = com::ubuntu::location;
> -namespace culs = com::ubuntu::location::service;
> -namespace dbus = core::dbus;
> -
> -int main(int argc, char** argv)
> -{
> -    cul::ProgramOptions options;
> -
> -    options.add("help", "Produces this help message");
> -    options.add(
> -        "bus", 
> -        "The well-known bus to announce the service upon", 
> -        std::string{"session"});
> -    options.add_composed<std::vector<std::string>>(
> -        "provider", 
> -        "The providers that should be added to the engine");
> -
> -    if (!options.parse_from_command_line_args(argc, argv))
> -        return EXIT_FAILURE;
> -
> -    if (options.value_count_for_key("help") > 0)
> -    {
> -        options.print_help(std::cout);
> -        return EXIT_SUCCESS;
> -    }
> -    
> -    if (options.value_count_for_key("provider") == 0)
> -    {
> -        std::cout << "A set of providers need to be specified. The following providers are known:" << std::endl;
> -        cul::ProviderFactory::instance().enumerate(
> -            [](const std::string& name, const cul::ProviderFactory::Factory&)
> -            {
> -                std::cout << "\t" << name << std::endl;
> -            });
> -        return EXIT_FAILURE;
> -    }
> -
> -    auto selected_providers = options.value_for_key<std::vector<std::string>>("provider");
> -
> -    std::map<std::string, cul::ProviderFactory::Configuration> config_lut;
> -    std::set<cul::Provider::Ptr> instantiated_providers;
> -
> -    for (const std::string& provider : selected_providers)
> -    {
> -        std::cout << "Instantiating and configuring: " << provider << std::endl;
> -        options.enumerate_unrecognized_options(
> -            [&config_lut, provider](const std::string& s)
> -            {
> -                std::stringstream in(s);
> -                std::string key, value;
> -                
> -                std::getline(in, key, '=');
> -                std::getline(in, value, '=');
> -                
> -                std::size_t pos = key.find(provider);
> -                if (pos == std::string::npos)
> -                    return;
> -                static const std::string option_marker{"--"};
> -                static const std::string scope_separator{"::"};
> -                key = key.erase(key.find_first_of(option_marker), option_marker.size()); 
> -                key = key.erase(key.find_first_of(provider), provider.size());
> -                key = key.erase(key.find_first_of(scope_separator), scope_separator.size()); 
> -                
> -                std::cout << "\t" << key << " -> " << value << std::endl;
> -
> -                config_lut[provider].put(key, value);
> -            });
> -
> -        try
> -        {
> -            auto p = cul::ProviderFactory::instance().create_provider_for_name_with_config(
> -                provider, 
> -                config_lut[provider]);
> -
> -            if (p)
> -                instantiated_providers.insert(p);
> -            else
> -                throw std::runtime_error("Problem instantiating provider");
> -            
> -        } catch(const std::runtime_error& e)
> -        {
> -            std::cerr << "Exception instantiating provider: " << e.what() << " ... Aborting now." << std::endl;
> -            return EXIT_FAILURE;
> -        }
> -    }
> -    
> -    static const std::map<std::string, dbus::WellKnownBus> lut = 
> -    {
> -        {"session", dbus::WellKnownBus::session},
> -        {"system", dbus::WellKnownBus::system},
> -    };
> -
> -    dbus::Bus::Ptr bus
> -    {
> -        new dbus::Bus{lut.at(options.value_for_key<std::string>("bus"))}
> -    };
> -
> -    bus->install_executor(dbus::asio::make_executor(bus));
> -
> -    culs::DefaultConfiguration config;
> -    
> -    auto location_service =
> -            dbus::announce_service_on_bus<
> -                culs::Interface, 
> -                culs::Implementation
> -            >(
> -                bus,
> -                config.the_engine(
> -                    instantiated_providers,
> -                    config.the_provider_selection_policy()),
> -                config.the_permission_manager());
> -    
> -    std::thread t{[bus](){bus->run();}};
> -    
> -    if (t.joinable())
> -        t.join();
> -
> -    return EXIT_SUCCESS;
> -}
> 
> === modified file 'src/location_service/com/ubuntu/location/service/program_options.h'
> --- src/location_service/com/ubuntu/location/service/program_options.h	2013-10-08 14:48:43 +0000
> +++ src/location_service/com/ubuntu/location/service/program_options.h	2014-06-24 16:02:38 +0000
> @@ -19,6 +19,8 @@
>  #include <boost/program_options/options_description.hpp>
>  #include <boost/program_options/variables_map.hpp>
>  
> +#include <core/dbus/well_known_bus.h>
> +
>  #include <functional>
>  #include <iostream>
>  
> @@ -28,8 +30,21 @@
>  
>  struct ProgramOptions
>  {
> +    struct Errors
> +    {
> +        struct OptionNotSet {};
> +    };
> +
> +    struct Options
> +    {
> +        static const char* bus() { return "bus"; }
> +    };
> +
>      ProgramOptions(bool do_allow_unregistered = true) : allow_unregistered(do_allow_unregistered)
>      {
> +        add(Options::bus(),
> +            "The well-known bus to connect to the service upon",
> +            std::string{"session"});
>      }
>  
>      ProgramOptions& add(const char* name, const char* desc)
> @@ -65,7 +80,7 @@
>          return *this;
>      }
>  
> -    bool parse_from_command_line_args(int argc, char** argv)
> +    bool parse_from_command_line_args(int argc, char const** argv)
>      {
>          try
>          {
> @@ -86,12 +101,51 @@
>          return true;
>      }
>  
> +    bool parse_from_environment()
> +    {
> +        try
> +        {
> +            auto parsed = boost::program_options::parse_environment(od, env_prefix);
> +            boost::program_options::store(parsed, vm);
> +            vm.notify();
> +        } catch(const std::runtime_error& e)
> +        {
> +            std::cerr << e.what() << std::endl;
> +            return false;
> +        }
> +
> +        return true;
> +    }
> +
> +    ProgramOptions& environment_prefix(const std::string& prefix)
> +    {
> +        env_prefix = prefix;
> +        return *this;
> +    }
> +
> +    core::dbus::WellKnownBus bus()
> +    {
> +        static const std::map<std::string, core::dbus::WellKnownBus> lut =
> +        {
> +            {"session", core::dbus::WellKnownBus::session},
> +            {"system", core::dbus::WellKnownBus::system},
> +        };
> +
> +        return lut.at(value_for_key<std::string>(Options::bus()));
> +    }
> +
>      template<typename T>
>      T value_for_key(const std::string& key)
>      {
>          return vm[key].as<T>();
>      }
>  
> +    template<typename T>
> +    T value_for_key(const std::string& key) const
> +    {
> +        return vm[key].as<T>();
> +    }
> +
>      std::size_t value_count_for_key(const std::string& key)
>      {
>          return vm.count(key);
> @@ -103,12 +157,19 @@
>              enumerator(s);
>      }
>  
> +    void print(std::ostream& out) const
> +    {
> +        for (const auto& pair : vm)
> +            out << pair.first << ": " << (pair.second.defaulted() ? "default" : "set") << std::endl;
> +    }
> +
>      void print_help(std::ostream& out)
>      {
>          out << od;
>      }
>  
>      bool allow_unregistered;
> +    std::string env_prefix;
>      boost::program_options::options_description od;
>      boost::program_options::variables_map vm;
>      std::vector<std::string> unrecognized;
> 
> === modified file 'src/location_service/com/ubuntu/location/service/session/implementation.cpp'
> --- src/location_service/com/ubuntu/location/service/session/implementation.cpp	2014-02-09 18:52:25 +0000
> +++ src/location_service/com/ubuntu/location/service/session/implementation.cpp	2014-06-24 16:02:38 +0000
> @@ -1,8 +1,10 @@
> -#include "com/ubuntu/location/service/session/implementation.h"
> +#include <com/ubuntu/location/service/session/implementation.h>
> +#include <com/ubuntu/location/logging.h>
>  
>  #include <functional>
>  #include <memory>
>  
> +namespace cu = com::ubuntu;
>  namespace cul = com::ubuntu::location;
>  namespace culs = com::ubuntu::location::service;
>  namespace culss = com::ubuntu::location::service::session;
> @@ -11,73 +13,117 @@
>  
>  struct culss::Implementation::Private
>  {
> -    Private(const Provider::Ptr& provider) : provider(provider)
> +    Provider::Ptr provider;
> +    struct
>      {
> -    }
> +        core::ScopedConnection position_updates;
> +        core::ScopedConnection velocity_updates;
> +        core::ScopedConnection heading_updates;
>  
> -    Provider::Ptr provider;
> -    ScopedChannelConnection position_updates_connection;
> -    ScopedChannelConnection velocity_updates_connection;
> -    ScopedChannelConnection heading_updates_connection;
> +        core::ScopedConnection position_status_updates;
> +        core::ScopedConnection heading_status_updates;
> +        core::ScopedConnection velocity_status_updates;
> +    } connections;
>  };
>  
> -culss::Implementation::Implementation(
> -    const dbus::Bus::Ptr& bus,
> -    const dbus::types::ObjectPath& session_path,
> -    const cul::Provider::Ptr& provider)
> -        : Skeleton(bus, session_path),
> -          d(new Private{provider})
> +culss::Implementation::Implementation(const cul::Provider::Ptr& provider)
> +        : Interface(),
> +          d(new Private
> +            {
> +                provider,
> +                {
> +                    provider->updates().position.connect(
> +                        [this](const Update<Position>& update)
> +                        {
> +                            updates().position = update;
> +                        }),
> +                    provider->updates().heading.connect(
> +                        [this](const Update<Heading>& update)
> +                        {
> +                            updates().heading = update;
> +                        }),
> +                    provider->updates().velocity.connect(
> +                        [this](const Update<Velocity>& update)
> +                        {
> +                            updates().velocity = update;
> +                        }),
> +                    updates().position_status.changed().connect(
> +                        [this](const Interface::Updates::Status& status)
> +                        {
> +                            switch(status)
> +                            {
> +                            case Interface::Updates::Status::enabled:
> +                                start_position_updates(); break;
> +                            case Interface::Updates::Status::disabled:
> +                                stop_position_updates(); break;
> +                            }
> +                        }),
> +                    updates().velocity_status.changed().connect(
> +                        [this](const Interface::Updates::Status& status)
> +                        {
> +                            switch(status)
> +                            {
> +                            case Interface::Updates::Status::enabled:
> +                                start_velocity_updates(); break;
> +                            case Interface::Updates::Status::disabled:
> +                                stop_velocity_updates(); break;
> +                            }
> +                        }),
> +                    updates().heading_status.changed().connect(
> +                        [this](const Interface::Updates::Status& status)
> +                        {
> +                            switch(status)
> +                            {
> +                            case Interface::Updates::Status::enabled:
> +                                start_heading_updates(); break;
> +                            case Interface::Updates::Status::disabled:
> +                                stop_heading_updates(); break;
> +                            }
> +                        })
> +                }
> +            })
>  {
> -    if (!provider)
> -        throw std::runtime_error("Cannot create implementation for null provider.");
> -    
> -    d->position_updates_connection =
> -            provider->subscribe_to_position_updates([this](const Update<Position>& update)
> -                                                    {
> -                                                        access_position_updates_channel()(update);
> -                                                    });
> -    d->heading_updates_connection =
> -            provider->subscribe_to_heading_updates([this](const Update<Heading>& update)
> -                                                   {
> -                                                       access_heading_updates_channel()(update);
> -                                                   });
> -    d->velocity_updates_connection =
> -            provider->subscribe_to_velocity_updates([this](const Update<Velocity>& update)
> -                                                    {
> -                                                        access_velocity_updates_channel()(update);
> -                                                    });
>  }
>  
>  culss::Implementation::~Implementation() noexcept
>  {
> +    stop_position_updates();
> +    stop_heading_updates();
> +    stop_velocity_updates();
>  }
>  
>  void culss::Implementation::start_position_updates()
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
>      d->provider->state_controller()->start_position_updates();
>  }
>  
>  void culss::Implementation::stop_position_updates() noexcept
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
>      d->provider->state_controller()->stop_position_updates();
>  }
>  
>  void culss::Implementation::start_velocity_updates()
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
>      d->provider->state_controller()->start_velocity_updates();
>  }
>  
>  void culss::Implementation::stop_velocity_updates() noexcept
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
>      d->provider->state_controller()->stop_velocity_updates();
>  }
>  
>  void culss::Implementation::start_heading_updates()
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
>      d->provider->state_controller()->start_heading_updates();
>  }
>  
>  void culss::Implementation::stop_heading_updates() noexcept
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
>      d->provider->state_controller()->stop_heading_updates();
>  }
> 
> === modified file 'src/location_service/com/ubuntu/location/service/session/interface.cpp'
> --- src/location_service/com/ubuntu/location/service/session/interface.cpp	2014-01-31 11:08:33 +0000
> +++ src/location_service/com/ubuntu/location/service/session/interface.cpp	2014-06-24 16:02:38 +0000
> @@ -15,7 +15,7 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/service/session/interface.h"
> +#include <com/ubuntu/location/service/session/interface.h>
>  
>  #include <core/dbus/codec.h>
>  #include <core/dbus/service.h>
> @@ -30,9 +30,7 @@
>  
>  struct culss::Interface::Private
>  {
> -    cul::Channel<cul::Update<cul::Position>> position_updates_channel;
> -    cul::Channel<cul::Update<cul::Heading>> heading_updates_channel;
> -    cul::Channel<cul::Update<cul::Velocity>> velocity_updates_channel;
> +    culss::Interface::Updates updates;
>  };
>  
>  culss::Interface::Interface() : d{new Private{}}
> @@ -43,32 +41,7 @@
>  {
>  }
>  
> -cul::ChannelConnection culss::Interface::install_position_updates_handler(std::function<void(const cul::Update<cul::Position>&)> handler)
> -{
> -    return d->position_updates_channel.connect(handler);
> -}
> -
> -cul::ChannelConnection culss::Interface::install_velocity_updates_handler(std::function<void(const cul::Update<cul::Velocity>&)> handler)
> -{
> -    return d->velocity_updates_channel.connect(handler);
> -}
> -
> -cul::ChannelConnection culss::Interface::install_heading_updates_handler(std::function<void(const cul::Update<cul::Heading>&)> handler)
> -{
> -    return d->heading_updates_channel.connect(handler);
> -}
> -
> -cul::Channel<cul::Update<cul::Position>>& culss::Interface::access_position_updates_channel()
> -{
> -    return d->position_updates_channel;
> -}
> -
> -cul::Channel<cul::Update<cul::Heading>>& culss::Interface::access_heading_updates_channel()
> -{
> -    return d->heading_updates_channel;
> -}
> -
> -cul::Channel<cul::Update<cul::Velocity>>& culss::Interface::access_velocity_updates_channel()
> -{
> -    return d->velocity_updates_channel;
> +culss::Interface::Updates& culss::Interface::updates()
> +{
> +    return d->updates;
>  }
> 
> === added file 'src/location_service/com/ubuntu/location/service/session/interface_p.h'
> --- src/location_service/com/ubuntu/location/service/session/interface_p.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/service/session/interface_p.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,228 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_INTERFACE_P_H_
> +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_INTERFACE_P_H_
> +
> +#include <com/ubuntu/location/service/session/interface.h>
> +
> +#include <core/dbus/codec.h>
> +#include <core/dbus/traits/service.h>
> +
> +struct com::ubuntu::location::service::session::Interface::UpdatePosition
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "UpdatePosition"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::UpdateVelocity
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "UpdateVelocity"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::UpdateHeading
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "UpdateHeading"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::StartPositionUpdates
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "StartPositionUpdates"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{5}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::StopPositionUpdates
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "StopPositionUpdates"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{5}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::StartVelocityUpdates
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "StartVelocityUpdates"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{5}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::StopVelocityUpdates
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "StopVelocityUpdates"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{5}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::StartHeadingUpdates
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "StartHeadingUpdates"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{5}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::StopHeadingUpdates
> +{
> +    typedef com::ubuntu::location::service::session::Interface Interface;
> +
> +    inline static const std::string& name()
> +    {
> +        static const std::string s
> +        {
> +            "StopHeadingUpdates"
> +        };
> +        return s;
> +    }
> +
> +    typedef void ResultType;
> +
> +    inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{5}; }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::Errors::ErrorParsingUpdate
> +{
> +    inline static std::string name()
> +    {
> +        return "com.ubuntu.location.Service.Session.ErrorParsingUpdate";
> +    }
> +};
> +
> +struct com::ubuntu::location::service::session::Interface::Errors::ErrorStartingUpdate
> +{
> +    inline static std::string name()
> +    {
> +        return "com.ubuntu.location.Service.Session.ErrorStartingUpdate";
> +    }
> +};
> +
> +namespace core
> +{
> +namespace dbus
> +{
> +namespace traits
> +{
> +template<>
> +struct Service<com::ubuntu::location::service::session::Interface>
> +{
> +    static const std::string& interface_name()
> +    {
> +        static const std::string s
> +        {
> +            "com.ubuntu.location.Service.Session"
> +        };
> +        return s;
> +    }
> +};
> +}
> +}
> +}
> +
> +#include <com/ubuntu/location/codec.h>
> +
> +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_SESSION_INTERFACE_P_H_
> 
> === modified file 'src/location_service/com/ubuntu/location/service/session/skeleton.cpp'
> --- src/location_service/com/ubuntu/location/service/session/skeleton.cpp	2014-03-05 12:57:39 +0000
> +++ src/location_service/com/ubuntu/location/service/session/skeleton.cpp	2014-06-24 16:02:38 +0000
> @@ -15,7 +15,11 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/service/session/skeleton.h"
> +#include <com/ubuntu/location/service/session/skeleton.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +
> +#include "interface_p.h"
>  
>  #include <core/dbus/message.h>
>  #include <core/dbus/object.h>
> @@ -29,172 +33,302 @@
>  
>  namespace dbus = core::dbus;
>  
> -struct culss::Skeleton::Private
> -{
> -    void handle_start_position_updates(const core::dbus::Message::Ptr& msg);
> -    void handle_stop_position_updates(const core::dbus::Message::Ptr& msg);
> -
> -    void handle_start_velocity_updates(const core::dbus::Message::Ptr& msg);
> -    void handle_stop_velocity_updates(const core::dbus::Message::Ptr& msg);
> -
> -    void handle_start_heading_updates(const core::dbus::Message::Ptr& msg);
> -    void handle_stop_heading_updates(const core::dbus::Message::Ptr& msg);
> -
> -    Skeleton* parent;
> -    dbus::Bus::Ptr bus;
> -    dbus::types::ObjectPath session_path;
> -    dbus::Object::Ptr object;
> -};
> -
> -culss::Skeleton::Skeleton(
> -    const dbus::Bus::Ptr& bus,
> -    const dbus::types::ObjectPath& session_path)
> -        : dbus::Skeleton<Interface>{bus},
> -    d(new Private
> -      {
> -          this,
> -          bus,
> -          session_path,
> -          access_service()->add_object_for_path(session_path)
> -      })
> -{
> -    d->object->install_method_handler<Interface::StartPositionUpdates>(
> -        std::bind(&Skeleton::Private::handle_start_position_updates,
> -                  std::ref(d),
> -                  std::placeholders::_1));
> -    d->object->install_method_handler<Interface::StopPositionUpdates>(
> -        std::bind(&Skeleton::Private::handle_stop_position_updates,
> -                  std::ref(d),
> -                  std::placeholders::_1));
> -    d->object->install_method_handler<Interface::StartVelocityUpdates>(
> -        std::bind(&Skeleton::Private::handle_start_velocity_updates,
> -                  std::ref(d),
> -                  std::placeholders::_1));
> -    d->object->install_method_handler<Interface::StopVelocityUpdates>(
> -        std::bind(&Skeleton::Private::handle_stop_velocity_updates,
> -                  std::ref(d),
> -                  std::placeholders::_1));
> -    d->object->install_method_handler<Interface::StartHeadingUpdates>(
> -        std::bind(&Skeleton::Private::handle_start_heading_updates,
> -                  std::ref(d),
> -                  std::placeholders::_1));
> -    d->object->install_method_handler<Interface::StopHeadingUpdates>(
> -        std::bind(&Skeleton::Private::handle_stop_heading_updates,
> -                  std::ref(d),
> -                  std::placeholders::_1));
> +namespace
> +{
> +dbus::Message::Ptr the_empty_reply()
> +{
> +    return dbus::Message::Ptr{};
> +}
> +}
> +
> +culss::Skeleton::Skeleton(const culss::Skeleton::Configuration& config)
> +        : dbus::Skeleton<Interface>{config.local.bus},
> +          configuration(config),
> +          object(access_service()->add_object_for_path(configuration.path)),
> +          connections
> +          {
> +              configuration.local.impl->updates().position.changed().connect(
> +                  [this](const cul::Update<cul::Position>& position)
> +                  {
> +                      on_position_changed(position);
> +                  }),
> +              configuration.local.impl->updates().heading.changed().connect(
> +                  [this](const cul::Update<cul::Heading>& heading)
> +                  {
> +                      on_heading_changed(heading);
> +                  }),
> +              configuration.local.impl->updates().velocity.changed().connect(
> +                  [this](const cul::Update<cul::Velocity>& velocity)
> +                  {
> +                      on_velocity_changed(velocity);
> +                  })
> +          }
> +{
> +    object->install_method_handler<Interface::StartPositionUpdates>([this](const dbus::Message::Ptr& msg)
> +    {
> +        on_start_position_updates(msg);
> +    });
> +
> +    object->install_method_handler<Interface::StopPositionUpdates>([this](const dbus::Message::Ptr& msg)
> +    {
> +        on_stop_position_updates(msg);
> +    });
> +
> +    object->install_method_handler<Interface::StartVelocityUpdates>([this](const dbus::Message::Ptr& msg)
> +    {
> +        on_start_velocity_updates(msg);
> +    });
> +
> +    object->install_method_handler<Interface::StopVelocityUpdates>([this](const dbus::Message::Ptr& msg)
> +    {
> +        on_stop_velocity_updates(msg);
> +    });
> +
> +    object->install_method_handler<Interface::StartHeadingUpdates>([this](const dbus::Message::Ptr& msg)
> +    {
> +        on_start_heading_updates(msg);
> +    });
> +
> +    object->install_method_handler<Interface::StopHeadingUpdates>([this](const dbus::Message::Ptr& msg)
> +    {
> +        on_stop_heading_updates(msg);
> +    });
>  }
>  
>  culss::Skeleton::~Skeleton() noexcept
>  {
> -    d->object->uninstall_method_handler<Interface::StartPositionUpdates>();
> -    d->object->uninstall_method_handler<Interface::StopPositionUpdates>();
> -    d->object->uninstall_method_handler<Interface::StartVelocityUpdates>();
> -    d->object->uninstall_method_handler<Interface::StopVelocityUpdates>();
> -    d->object->uninstall_method_handler<Interface::StartHeadingUpdates>();
> -    d->object->uninstall_method_handler<Interface::StopHeadingUpdates>();
> +    object->uninstall_method_handler<Interface::StartPositionUpdates>();
> +    object->uninstall_method_handler<Interface::StopPositionUpdates>();
> +    object->uninstall_method_handler<Interface::StartVelocityUpdates>();
> +    object->uninstall_method_handler<Interface::StopVelocityUpdates>();
> +    object->uninstall_method_handler<Interface::StartHeadingUpdates>();
> +    object->uninstall_method_handler<Interface::StopHeadingUpdates>();
> +}
> +
> +void culss::Skeleton::on_start_position_updates(const core::dbus::Message::Ptr& msg)
> +{
> +    VLOG(10) << "MethodHandler for Interface::StartPositionUpdates";
> +
> +    auto reply = the_empty_reply();
> +
> +    try
> +    {
> +        configuration.local.impl->updates().position_status = culss::Interface::Updates::Status::enabled;
> +        reply = dbus::Message::make_method_return(msg);
> +    } catch(const std::runtime_error& e)
> +    {
> +        // We only provide a generic error message to avoid leaking
> +        // any sort of private data to unprivileged clients.
> +        reply = core::dbus::Message::make_error(
> +                    msg,
> +                    Interface::Errors::ErrorStartingUpdate::name(),
> +                    "Could not enable position updates");
> +        LOG(ERROR) << e.what();
> +    }
> +
> +    try
> +    {
> +        configuration.local.bus->send(reply);
> +    } catch(const std::exception& e)
> +    {
> +        LOG(ERROR) << e.what();
> +    }
> +}
> +
> +void culss::Skeleton::on_stop_position_updates(const core::dbus::Message::Ptr& msg)
> +{
> +    VLOG(10) << "MethodHandler for Interface::StopPositionUpdates";
> +    auto reply = the_empty_reply();
> +
> +    try
> +    {
> +        configuration.local.impl->updates().position_status = culss::Interface::Updates::Status::disabled;
> +        reply = dbus::Message::make_method_return(msg);
> +    } catch(const std::runtime_error& e)
> +    {
> +        // We only provide a generic error message to avoid leaking
> +        // any sort of private data to unprivileged clients.
> +        reply = core::dbus::Message::make_error(
> +                    msg,
> +                    Interface::Errors::ErrorStartingUpdate::name(),
> +                    "Could not disable position updates");
> +        LOG(ERROR) << e.what();
> +    }
> +
> +    try
> +    {
> +        configuration.local.bus->send(reply);
> +    } catch(const std::exception& e)
> +    {
> +        LOG(ERROR) << e.what();
> +    }
> +}
> +
> +void culss::Skeleton::on_start_heading_updates(const core::dbus::Message::Ptr& msg)
> +{
> +    VLOG(10) << "MethodHandler for Interface::StartHeadingUpdates";
> +    auto reply = the_empty_reply();
> +
> +    try
> +    {
> +        configuration.local.impl->updates().position_status = culss::Interface::Updates::Status::enabled;
> +        reply = dbus::Message::make_method_return(msg);
> +    } catch(const std::runtime_error& e)
> +    {
> +        // We only provide a generic error message to avoid leaking
> +        // any sort of private data to unprivileged clients.
> +        reply = core::dbus::Message::make_error(
> +                    msg,
> +                    Interface::Errors::ErrorStartingUpdate::name(),
> +                    "Could not enable position updates");
> +        LOG(ERROR) << e.what();
> +    }
> +
> +    try
> +    {
> +        configuration.local.bus->send(reply);
> +    } catch(const std::exception& e)
> +    {
> +        LOG(ERROR) << e.what();
> +    }
> +}
> +
> +void culss::Skeleton::on_stop_heading_updates(const core::dbus::Message::Ptr& msg)
> +{
> +    VLOG(10) << "MethodHandler for Interface::StopHeadingUpdates";
> +    auto reply = the_empty_reply();
> +    try
> +    {
> +        configuration.local.impl->updates().heading_status = culss::Interface::Updates::Status::disabled;
> +        reply = dbus::Message::make_method_return(msg);
> +    } catch(const std::runtime_error& e)
> +    {
> +        // We only provide a generic error message to avoid leaking
> +        // any sort of private data to unprivileged clients.
> +        reply = core::dbus::Message::make_error(
> +                    msg,
> +                    Interface::Errors::ErrorStartingUpdate::name(),
> +                    "Could not enable position updates");
> +        LOG(ERROR) << e.what();
> +    }
> +
> +    try
> +    {
> +        configuration.local.bus->send(reply);
> +    } catch(const std::exception& e)
> +    {
> +        LOG(ERROR) << e.what();
> +    }
> +}
> +
> +void culss::Skeleton::on_start_velocity_updates(const core::dbus::Message::Ptr& msg)
> +{
> +    VLOG(10) << "MethodHandler for Interface::StartVelocityUpdates";
> +    auto reply = the_empty_reply();
> +    try
> +    {
> +        configuration.local.impl->updates().velocity_status = culss::Interface::Updates::Status::enabled;
> +        reply = dbus::Message::make_method_return(msg);
> +    } catch(const std::runtime_error& e)
> +    {
> +        // We only provide a generic error message to avoid leaking
> +        // any sort of private data to unprivileged clients.
> +        reply = core::dbus::Message::make_error(
> +                    msg,
> +                    Interface::Errors::ErrorStartingUpdate::name(),
> +                    "Could not enable position updates");
> +        LOG(ERROR) << e.what();
> +    }
> +
> +    try
> +    {
> +        configuration.local.bus->send(reply);
> +    } catch(const std::exception& e)
> +    {
> +        LOG(ERROR) << e.what();
> +    }
> +}
> +
> +void culss::Skeleton::on_stop_velocity_updates(const core::dbus::Message::Ptr& msg)
> +{
> +    VLOG(10) << "MethodHandler for Interface::StopVelocityUpdates";
> +    auto reply = the_empty_reply();
> +    try
> +    {
> +        configuration.local.impl->updates().velocity_status = culss::Interface::Updates::Status::disabled;
> +        reply = dbus::Message::make_method_return(msg);
> +    } catch(const std::runtime_error& e)
> +    {
> +        // We only provide a generic error message to avoid leaking
> +        // any sort of private data to unprivileged clients.
> +        reply = core::dbus::Message::make_error(
> +                    msg,
> +                    Interface::Errors::ErrorStartingUpdate::name(),
> +                    "Could not enable position updates");
> +        LOG(ERROR) << e.what();
> +    }
> +
> +    try
> +    {
> +        configuration.local.bus->send(reply);
> +    } catch(const std::exception& e)
> +    {
> +        LOG(ERROR) << e.what();
> +    }
> +}
> +
> +// Invoked whenever the actual session impl. for the session reports a position update.
> +void culss::Skeleton::on_position_changed(const cul::Update<cul::Position>& position)
> +{
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +    try
> +    {
> +        configuration.remote.object->invoke_method_synchronously<culs::session::Interface::UpdatePosition, void>(position);
> +    } catch(const std::exception&)
> +    {
> +        // We consider the session to be dead once we hit an exception here.
> +        // We thus remove it from the central and end its lifetime.
> +        // on_session_died();
> +    } catch(...)
> +    {
> +    }
> +}
> +
> +// Invoked whenever the actual session impl. reports a heading update.
> +void culss::Skeleton::on_heading_changed(const cul::Update<cul::Heading>& heading)
> +{
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +    try
> +    {
> +        configuration.remote.object->invoke_method_synchronously<culs::session::Interface::UpdateHeading, void>(heading);
> +    } catch(const std::exception&)
> +    {
> +        // We consider the session to be dead once we hit an exception here.
> +        // We thus remove it from the central and end its lifetime.
> +        //on_session_died();
> +    } catch(...)
> +    {
> +    }
> +}
> +
> +// Invoked whenever the actual session impl. reports a velocity update.
> +void culss::Skeleton::on_velocity_changed(const cul::Update<cul::Velocity>& velocity)
> +{
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +    try
> +    {
> +        configuration.remote.object->invoke_method_synchronously<culs::session::Interface::UpdateVelocity, void>(velocity);
> +    } catch(const std::exception&)
> +    {
> +        // We consider the session to be dead once we hit an exception here.
> +        // We thus remove it from the central and end its lifetime.
> +        // on_session_died();
> +    } catch(...)
> +    {
> +    }
>  }
>  
>  const dbus::types::ObjectPath& culss::Skeleton::path() const
>  {
> -    return d->session_path;
> -}
> -
> -void culss::Skeleton::Private::handle_start_position_updates(const core::dbus::Message::Ptr& msg)
> -{
> -    try
> -    {
> -        parent->start_position_updates();
> -        auto reply = dbus::Message::make_method_return(msg);
> -        bus->send(reply);
> -    } catch(const std::runtime_error& e)
> -    {
> -        auto error = core::dbus::Message::make_error(
> -                    msg,
> -                    Interface::Errors::ErrorStartingUpdate::name(),
> -                    e.what());
> -
> -        bus->send(error);
> -    }
> -}
> -
> -void culss::Skeleton::Private::handle_stop_position_updates(const core::dbus::Message::Ptr& msg)
> -{
> -    try
> -    {
> -        parent->stop_position_updates();
> -        auto reply = core::dbus::Message::make_method_return(msg);
> -        bus->send(reply);
> -    } catch(const std::runtime_error& e)
> -    {
> -        auto error = core::dbus::Message::make_error(
> -                    msg,
> -                    Interface::Errors::ErrorStoppingUpdate::name(),
> -                    e.what());
> -
> -        bus->send(error);
> -    }
> -}
> -
> -void culss::Skeleton::Private::handle_start_velocity_updates(const core::dbus::Message::Ptr& msg)
> -{
> -    try
> -    {
> -        parent->start_velocity_updates();
> -        auto reply = core::dbus::Message::make_method_return(msg);
> -        bus->send(reply);
> -    } catch(const std::runtime_error& e)
> -    {
> -        auto error = core::dbus::Message::make_error(msg, Interface::Errors::ErrorStartingUpdate::name(), e.what());
> -        bus->send(error);
> -    }
> -}
> -
> -void culss::Skeleton::Private::handle_stop_velocity_updates(const core::dbus::Message::Ptr& msg)
> -{
> -    try
> -    {
> -        parent->stop_velocity_updates();
> -        auto reply = core::dbus::Message::make_method_return(msg);
> -        bus->send(reply);
> -    } catch(const std::runtime_error& e)
> -    {
> -        auto error = core::dbus::Message::make_error(
> -                    msg,
> -                    Interface::Errors::ErrorStoppingUpdate::name(),
> -                    e.what());
> -
> -        bus->send(error);
> -    }
> -}
> -
> -void culss::Skeleton::Private::handle_start_heading_updates(const core::dbus::Message::Ptr& msg)
> -{
> -    try
> -    {
> -        parent->start_heading_updates();
> -        auto reply = core::dbus::Message::make_method_return(msg);
> -        bus->send(reply);
> -    } catch(const std::runtime_error& e)
> -    {
> -        auto error = core::dbus::Message::make_error(msg, Interface::Errors::ErrorStartingUpdate::name(), e.what());
> -        bus->send(error);
> -    }
> -}
> -
> -void culss::Skeleton::Private::handle_stop_heading_updates(const core::dbus::Message::Ptr& msg)
> -{
> -    try
> -    {
> -        parent->stop_heading_updates();
> -        auto reply = core::dbus::Message::make_method_return(msg);
> -        bus->send(reply);
> -    } catch(const std::runtime_error& e)
> -    {
> -        auto error = core::dbus::Message::make_error(
> -                    msg,
> -                    Interface::Errors::ErrorStoppingUpdate::name(),
> -                    e.what());
> -
> -        bus->send(error);
> -    }
> +    return configuration.path;
>  }
> 
> === modified file 'src/location_service/com/ubuntu/location/service/session/stub.cpp'
> --- src/location_service/com/ubuntu/location/service/session/stub.cpp	2014-03-05 12:57:39 +0000
> +++ src/location_service/com/ubuntu/location/service/session/stub.cpp	2014-06-24 16:02:38 +0000
> @@ -16,9 +16,11 @@
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
>  
> -#include "com/ubuntu/location/service/session/stub.h"
> -
> -#include "com/ubuntu/location/logging.h"
> +#include <com/ubuntu/location/service/session/stub.h>
> +
> +#include "interface_p.h"
> +
> +#include <com/ubuntu/location/logging.h>
>  
>  #include <core/dbus/stub.h>
>  
> @@ -32,21 +34,65 @@
>  
>  struct culss::Stub::Private
>  {
> -    void update_heading(const core::dbus::Message::Ptr& msg);
> -    void update_position(const core::dbus::Message::Ptr& msg);
> -    void update_velocity(const core::dbus::Message::Ptr& msg);
> +    Private(Stub* parent,
> +            const dbus::types::ObjectPath& path,
> +            const dbus::Object::Ptr& object,
> +            const core::Connection& position,
> +            const core::Connection& velocity,
> +            const core::Connection& heading)
> +        : parent(parent),
> +          session_path(path),
> +          object(object),
> +          position(position),
> +          velocity(velocity),
> +          heading(heading)
> +    {
> +    }
> +
> +    void update_heading(const dbus::Message::Ptr& msg);
> +    void update_position(const dbus::Message::Ptr& msg);
> +    void update_velocity(const dbus::Message::Ptr& msg);
>  
>      Stub* parent;
>      dbus::types::ObjectPath session_path;
>      dbus::Object::Ptr object;
> +    core::ScopedConnection position;
> +    core::ScopedConnection velocity;
> +    core::ScopedConnection heading;
> +
>  };
>  
>  culss::Stub::Stub(const dbus::Bus::Ptr& bus,
>                    const dbus::types::ObjectPath& session_path)
>          : dbus::Stub<culss::Interface>(bus),
> -        d(new Private{this,
> -                        session_path,
> -                        access_service()->add_object_for_path(session_path)})
> +        d(new Private(this,
> +                      session_path,
> +                      access_service()->add_object_for_path(session_path),
> +                      updates().position_status.changed().connect([this](const Interface::Updates::Status& status)
> +                      {
> +                          switch(status)
> +                          {
> +                          case Interface::Updates::Status::enabled: start_position_updates(); break;
> +                          case Interface::Updates::Status::disabled: stop_position_updates(); break;
> +                          }
> +                      }),
> +                      updates().velocity_status.changed().connect([this](const Interface::Updates::Status& status)
> +                      {
> +                          switch(status)
> +                          {
> +                          case Interface::Updates::Status::enabled: start_velocity_updates(); break;
> +                          case Interface::Updates::Status::disabled: stop_velocity_updates(); break;
> +                          }
> +                      }),
> +                      updates().heading_status.changed().connect([this](const Interface::Updates::Status& status)
> +                      {
> +                          switch(status)
> +                          {
> +                          case Interface::Updates::Status::enabled: start_heading_updates(); break;
> +                          case Interface::Updates::Status::disabled: stop_heading_updates(); break;
> +                          }
> +                      })
> +                      ))
>  {
>      d->object->install_method_handler<culss::Interface::UpdatePosition>(
>          std::bind(&Stub::Private::update_position,
> @@ -62,7 +108,18 @@
>                    std::placeholders::_1));
>  }
>  
> -culss::Stub::~Stub() noexcept {}
> +culss::Stub::~Stub() noexcept
> +{
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
> +    //stop_position_updates();
> +    //stop_heading_updates();
> +    //stop_velocity_updates();
> +
> +    d->object->uninstall_method_handler<culss::Interface::UpdatePosition>();
> +    d->object->uninstall_method_handler<culss::Interface::UpdateHeading>();
> +    d->object->uninstall_method_handler<culss::Interface::UpdateVelocity>();
> +}
>  
>  const dbus::types::ObjectPath& culss::Stub::path() const
>  {
> @@ -71,19 +128,30 @@
>  
>  void culss::Stub::start_position_updates()
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      auto result = d->object->transact_method<Interface::StartPositionUpdates,void>();
>  
>      if (result.is_error())
> -        throw std::runtime_error(result.error().print());
> +    {
> +        std::stringstream ss; ss << __PRETTY_FUNCTION__ << ": " << result.error().print();
> +        throw std::runtime_error(ss.str());
> +    }
>  }
>  
>  void culss::Stub::stop_position_updates() noexcept
>  {
> -    try {
> -        auto result = d->object->transact_method<Interface::StopPositionUpdates,void>();
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
> +    try
> +    {
> +        auto result = d->object->invoke_method_synchronously<Interface::StopPositionUpdates,void>();
>  
>          if (result.is_error())
> -            LOG(WARNING) << result.error();
> +        {
> +            std::stringstream ss; ss << __PRETTY_FUNCTION__ << ": " << result.error().print();
> +            throw std::runtime_error(ss.str());
> +        }
>      } catch(const std::runtime_error& e)
>      {
>          LOG(WARNING) << e.what();
> @@ -92,19 +160,29 @@
>  
>  void culss::Stub::start_velocity_updates()
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      auto result = d->object->transact_method<Interface::StartVelocityUpdates,void>();
>  
>      if (result.is_error())
> -        throw std::runtime_error(result.error().print());
> +    {
> +        std::stringstream ss; ss << __PRETTY_FUNCTION__ << ": " << result.error().print();
> +        throw std::runtime_error(ss.str());
> +    }
>  }
>  
>  void culss::Stub::stop_velocity_updates() noexcept
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      try {
>          auto result = d->object->transact_method<Interface::StopVelocityUpdates,void>();
>  
>          if (result.is_error())
> -            LOG(WARNING) << result.error();
> +        {
> +            std::stringstream ss; ss << __PRETTY_FUNCTION__ << ": " << result.error().print();
> +            throw std::runtime_error(ss.str());
> +        }
>      } catch(const std::runtime_error& e)
>      {
>          LOG(WARNING) << e.what();
> @@ -113,60 +191,88 @@
>  
>  void culss::Stub::start_heading_updates()
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      auto result = d->object->transact_method<Interface::StartHeadingUpdates,void>();
>  
>      if (result.is_error())
> -        throw std::runtime_error(result.error().print());
> +    {
> +        std::stringstream ss; ss << __PRETTY_FUNCTION__ << ": " << result.error().print();
> +        throw std::runtime_error(ss.str());
> +    }
>  }
>  
>  void culss::Stub::stop_heading_updates() noexcept
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      try {
>          auto result = d->object->transact_method<Interface::StopHeadingUpdates,void>();
>  
>          if (result.is_error())
> -            LOG(WARNING) << result.error();
> +        {
> +            std::stringstream ss; ss << __PRETTY_FUNCTION__ << ": " << result.error().print();
> +            throw std::runtime_error(ss.str());
> +        }
>      } catch(const std::runtime_error& e)
>      {
>          LOG(WARNING) << e.what();
>      }
>  }
>  
> -void culss::Stub::Private::update_heading(const core::dbus::Message::Ptr& incoming)
> +void culss::Stub::Private::update_heading(const dbus::Message::Ptr& incoming)
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      try
>      {
>          Update<Heading> update; incoming->reader() >> update;
> -        parent->access_heading_updates_channel()(update);
> +        parent->updates().heading = update;
>          parent->access_bus()->send(dbus::Message::make_method_return(incoming));
>      } catch(const std::runtime_error& e)
>      {
> -        parent->access_bus()->send(dbus::Message::make_error(incoming, Interface::Errors::ErrorParsingUpdate::name(), e.what()));
> +        parent->access_bus()->send(
> +                    dbus::Message::make_error(
> +                        incoming,
> +                        Interface::Errors::ErrorParsingUpdate::name(),
> +                        e.what()));
>      }
>  }
>  
> -void culss::Stub::Private::update_position(const core::dbus::Message::Ptr& incoming)
> +void culss::Stub::Private::update_position(const dbus::Message::Ptr& incoming)
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      try
>      {
>          Update<Position> update; incoming->reader() >> update;
> -        parent->access_position_updates_channel()(update);
> +        parent->updates().position = update;
>          parent->access_bus()->send(dbus::Message::make_method_return(incoming));
>      } catch(const std::runtime_error& e)
>      {
> -        parent->access_bus()->send(dbus::Message::make_error(incoming, Interface::Errors::ErrorParsingUpdate::name(), e.what()));
> +        parent->access_bus()->send(
> +                    dbus::Message::make_error(
> +                        incoming,
> +                        Interface::Errors::ErrorParsingUpdate::name(),
> +                        e.what()));
>      }
>  }
>  
> -void culss::Stub::Private::update_velocity(const core::dbus::Message::Ptr& incoming)
> +void culss::Stub::Private::update_velocity(const dbus::Message::Ptr& incoming)
>  {
> +    VLOG(10) << __PRETTY_FUNCTION__;
> +
>      try
>      {
>          Update<Velocity> update; incoming->reader() >> update;
> -        parent->access_velocity_updates_channel()(update);
> +        parent->updates().velocity = update;
>          parent->access_bus()->send(dbus::Message::make_method_return(incoming));
>      } catch(const std::runtime_error& e)
>      {
> -        parent->access_bus()->send(dbus::Message::make_error(incoming, Interface::Errors::ErrorParsingUpdate::name(), e.what()));
> +        parent->access_bus()->send(
> +                    dbus::Message::make_error(
> +                        incoming,
> +                        Interface::Errors::ErrorParsingUpdate::name(),
> +                        e.what()));
>      }
>  }
> 
> === modified file 'src/location_service/com/ubuntu/location/service/skeleton.cpp'
> --- src/location_service/com/ubuntu/location/service/skeleton.cpp	2014-03-05 13:09:17 +0000
> +++ src/location_service/com/ubuntu/location/service/skeleton.cpp	2014-06-24 16:02:38 +0000
> @@ -15,13 +15,11 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/service/skeleton.h"
> -
> -#include "com/ubuntu/location/logging.h"
> -
> -#include <core/dbus/dbus.h>
> -#include <core/dbus/object.h>
> -#include <core/dbus/skeleton.h>
> +#include <com/ubuntu/location/service/skeleton.h>
> +#include <com/ubuntu/location/service/session/skeleton.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +
>  #include <core/dbus/types/object_path.h>
>  
>  namespace cul = com::ubuntu::location;
> @@ -32,220 +30,169 @@
>  
>  namespace
>  {
> -
> -template<typename SessionType>
> -struct SessionStore
> -{
> -    typedef std::shared_ptr<SessionStore> Ptr;
> -
> -    SessionStore() = default;
> -    SessionStore(const SessionStore&) = delete;
> -    SessionStore& operator=(const SessionStore&) = delete;
> -    virtual ~SessionStore() = default;
> -
> -    virtual void remove_session(const std::shared_ptr<SessionType>& session) = 0;
> -};
> -
> -struct SessionWrapper : public std::enable_shared_from_this<SessionWrapper>
> -{
> -    typedef std::shared_ptr<SessionWrapper> Ptr;
> -
> -    SessionWrapper(const SessionStore<SessionWrapper>::Ptr& session_store,
> -		   const culss::Interface::Ptr& session,
> -		   core::dbus::Service::Ptr service,
> -		   core::dbus::Object::Ptr object)
> -	    : session_store(session_store),
> -	      session{session},
> -	      remote(service, object)
> -    {
> -	session->install_position_updates_handler(std::bind(&SessionWrapper::on_position_update, this, std::placeholders::_1));
> -	session->install_velocity_updates_handler(std::bind(&SessionWrapper::on_velocity_update, this, std::placeholders::_1));
> -	session->install_heading_updates_handler(std::bind(&SessionWrapper::on_heading_update, this, std::placeholders::_1));
> -    }
> -
> -    const core::dbus::types::ObjectPath& path() const
> -    {
> -	return session->path();
> -    }
> -
> -    void on_session_died() noexcept
> -    {
> -        std::cout << __PRETTY_FUNCTION__ << std::endl;
> -	VLOG(1) << "Session died, removing from store and stopping all updates.";
> -
> -	auto thiz = shared_from_this();
> -	try
> -	{
> -	    session_store->remove_session(thiz);
> -	    session->stop_position_updates();
> -	    session->stop_heading_updates();
> -	    session->stop_velocity_updates();
> -	} catch(const std::runtime_error& e)
> -	{
> -	    LOG(ERROR) << "Error while stopping updates for died session: " << e.what();
> -	}
> -    }
> -
> -    void on_position_update(const cul::Update<cul::Position>& position)
> -    {
> -	try
> -	{
> -        auto result = remote.session->transact_method<culs::session::Interface::UpdatePosition, void>(position);
> -        if (result.is_error())
> -        {
> -            LOG(ERROR) << result.error().print();
> -            on_session_died();
> -        }
> -	} catch(const std::runtime_error& e)
> -	{
> -	    // We consider the session to be dead once we hit an exception here.
> -	    // We thus remove it from the central and end its lifetime.
> -        on_session_died();
> -	}
> -    }
> -
> -    void on_velocity_update(const cul::Update<cul::Velocity>& velocity)
> -    {
> -	try
> -	{
> -        auto result = remote.session->transact_method<culs::session::Interface::UpdateVelocity, void>(velocity);
> -        if (result.is_error())
> -        {
> -            LOG(ERROR) << result.error().print();
> -            on_session_died();
> -        }
> -	} catch(const std::runtime_error& e)
> -	{
> -	    // We consider the session to be dead once we hit an exception here.
> -	    // We thus remove it from the central and end its lifetime.
> -        on_session_died();
> -	}
> -    }
> -
> -    void on_heading_update(const cul::Update<cul::Heading>& heading)
> -    {
> -	try
> -	{
> -        auto result = remote.session->transact_method<culs::session::Interface::UpdateHeading, void>(heading);
> -        if (result.is_error())
> -        {
> -            LOG(ERROR) << result.error().print();
> -            on_session_died();
> -        }
> -	} catch(const std::runtime_error& e)
> -	{
> -	    // We consider the session to be dead once we hit an exception here.
> -	    // We thus remove it from the central and end its lifetime.
> -        on_session_died();
> -	}
> -    }
> -
> -    SessionStore<SessionWrapper>::Ptr session_store;
> -    culs::session::Interface::Ptr session;
> -    struct Remote
> -    {
> -	explicit Remote(const dbus::Service::Ptr& service,
> -			const dbus::Object::Ptr& session)
> -		: service(service),
> -		  session(session)
> -	{
> -	}
> -	
> -	dbus::Service::Ptr service;
> -	dbus::Object::Ptr session;
> -    } remote;
> -};
> -}
> -
> -struct culs::Skeleton::Private : public SessionStore<SessionWrapper>, std::enable_shared_from_this<culs::Skeleton::Private>
> -{
> -    Private(Skeleton* parent, const dbus::Bus::Ptr& connection, const culs::PermissionManager::Ptr& permission_manager)
> -	: parent(parent),
> -	  permission_manager(permission_manager),
> -	  daemon(connection),
> -	  object(parent->access_service()->add_object_for_path(culs::Interface::path()))
> -    {
> -	object->install_method_handler<culs::Interface::CreateSessionForCriteria>(
> -	    std::bind(&culs::Skeleton::Private::handle_create_session_for_criteria, this, std::placeholders::_1));
> -    }
> -
> -    ~Private() noexcept {}
> -
> -    void handle_create_session_for_criteria(const core::dbus::Message::Ptr& in);
> -    void remove_session(const std::shared_ptr<SessionWrapper>& session);
> -
> -    Skeleton* parent;
> -    PermissionManager::Ptr permission_manager;
> -    dbus::DBus daemon;
> -    dbus::Object::Ptr object;
> -    std::mutex guard;
> -    std::map<dbus::types::ObjectPath, std::shared_ptr<SessionWrapper>> session_store;
> -};
> -
> -culs::Skeleton::Skeleton(const dbus::Bus::Ptr& connection, const culs::PermissionManager::Ptr& permission_manager)
> -	: dbus::Skeleton<culs::Interface>(connection), d{new Private{this, connection, permission_manager}}
> -{
> +dbus::Message::Ptr the_empty_reply()
> +{
> +    return dbus::Message::Ptr{};
> +}
> +}
> +
> +culs::Skeleton::DBusDaemonCredentialsResolver::DBusDaemonCredentialsResolver(const dbus::Bus::Ptr& bus)
> +    : daemon(bus)
> +{
> +}
> +
> +culs::Credentials
> +culs::Skeleton::DBusDaemonCredentialsResolver::resolve_credentials_for_incoming_message(const dbus::Message::Ptr& msg)
> +{
> +    return culs::Credentials
> +    {
> +        daemon.get_connection_unix_process_id(msg->sender()),
> +        daemon.get_connection_unix_user(msg->sender())
> +    };
> +}
> +
> +core::dbus::types::ObjectPath culs::Skeleton::ObjectPathGenerator::object_path_for_caller_credentials(const culs::Credentials&)
> +{
> +    static std::uint32_t index{0};
> +    std::stringstream ss; ss << "/sessions/" << index++;
> +
> +    return core::dbus::types::ObjectPath{ss.str()};
> +}
> +
> +
> +culs::Skeleton::Skeleton(const culs::Skeleton::Configuration& configuration)
> +    : dbus::Skeleton<culs::Interface>(configuration.incoming),
> +      configuration(configuration),
> +      object(access_service()->add_object_for_path(culs::Interface::path())),
> +      properties
> +      {
> +          object->get_property<culs::Interface::Properties::DoesSatelliteBasedPositioning>(),
> +          object->get_property<culs::Interface::Properties::DoesReportCellAndWifiIds>(),
> +          object->get_property<culs::Interface::Properties::IsOnline>(),
> +          object->get_property<culs::Interface::Properties::VisibleSpaceVehicles>()
> +      }
> +{
> +    object->install_method_handler<culs::Interface::CreateSessionForCriteria>([this](const dbus::Message::Ptr& msg)
> +    {
> +        handle_create_session_for_criteria(msg);
> +    });
>  }
>  
>  culs::Skeleton::~Skeleton() noexcept
>  {
> +    object->uninstall_method_handler<culs::Interface::CreateSessionForCriteria>();
>  }
>  
> -void culs::Skeleton::Private::handle_create_session_for_criteria(const core::dbus::Message::Ptr& in)
> +void culs::Skeleton::handle_create_session_for_criteria(const dbus::Message::Ptr& in)
>  {
> +    VLOG(1) << __PRETTY_FUNCTION__;
> +
>      auto sender = in->sender();
> +    auto reply = the_empty_reply();
>  
>      try
>      {
> -	Criteria criteria;
> -	in->reader() >> criteria;
> -
> -	Credentials credentials
> -	{
> -	    static_cast<pid_t>(daemon.get_connection_unix_process_id(sender)),
> -	    static_cast<uid_t>(daemon.get_connection_unix_user(sender))
> -	};
> -
> -	if (PermissionManager::Result::rejected == permission_manager->check_permission_for_credentials(criteria, credentials))
> -	    throw std::runtime_error("Client lacks permissions to access the service with the given criteria");
> -
> -	auto session = parent->create_session_for_criteria(criteria);
> -
> -    auto service = dbus::Service::use_service(parent->access_bus(), in->sender());
> -    auto object = service->object_for_path(session->path());
> -
> +        Criteria criteria;
> +        in->reader() >> criteria;
> +
> +        auto credentials =
> +            configuration.credentials_resolver->resolve_credentials_for_incoming_message(in);
> +
> +        auto result =
> +            configuration.permission_manager->check_permission_for_credentials(criteria, credentials);
> +
> +        if (PermissionManager::Result::rejected == result) throw std::runtime_error
> +        {
> +            "Client lacks permissions to access the service with the given criteria"
> +        };
> +
> +        auto path =
> +            configuration.object_path_generator->object_path_for_caller_credentials(credentials);
> +
> +        auto stub =
> +            dbus::Service::use_service(configuration.outgoing, sender);
> +
> +        culss::Skeleton::Configuration config
> +        {
> +            path,
> +            culss::Skeleton::Local
> +            {
> +                create_session_for_criteria(criteria),
> +                configuration.incoming
> +            },
> +            culss::Skeleton::Remote
> +            {
> +                stub->object_for_path(path)
> +            }
> +        };
> +
> +        culss::Interface::Ptr session
> +        {
> +            new culss::Skeleton{config}
> +        };
> +
> +        if (not add_to_session_store_for_path(path, session))
> +        {
> +            reply = dbus::Message::make_error(
> +                        in,
> +                        culs::Interface::Errors::CreatingSession::name(),
> +                        "Refused to create second session for same process");
> +        } else
> +        {
> +            reply = dbus::Message::make_method_return(in);
> +            reply->writer() << path;
> +        }
> +
> +    } catch(const std::exception& e)
>      {
> -        std::lock_guard<std::mutex> lg(guard);
> -
> -        auto wrapper = SessionWrapper::Ptr{new SessionWrapper{shared_from_this(), session, service, object}};
> -
> -        bool inserted = false;
> -        std::tie(std::ignore, inserted) = session_store.insert(std::make_pair(session->path(), wrapper));
> -
> -        auto reply = dbus::Message::make_method_return(in);
> -        reply->writer() << session->path();
> -        parent->access_bus()->send(reply);
> -
> -        if (!inserted)
> -            throw std::runtime_error("Could not insert duplicate session into store.");
> +        // We only send a very generic error message to the client to avoid
> +        // leaking any sort of internal error handling details to untrusted
> +        // apps.
> +        reply = dbus::Message::make_error(
> +                    in,
> +                    culs::Interface::Errors::CreatingSession::name(),
> +                    "Error creating session");
> +        // We log the error for debugging purposes.
> +        LOG(ERROR) << "Error creating session: " << e.what();
>      }
>  
> -    } catch(const std::runtime_error& e)
> -    {
> -    parent->access_bus()->send(
> -        dbus::Message::make_error(
> -            in,
> -            culs::Interface::Errors::CreatingSession::name(),
> -            e.what()));
> -
> -    LOG(ERROR) << "Error creating session: " << e.what();
> +    // We are done processing the request and try to send out the result to the client.
> +    try
> +    {
> +        configuration.incoming->send(reply);
> +    } catch(const std::exception& e)
> +    {
> +        // We log the error for debugging purposes.
> +        LOG(ERROR) << "Error sending reply to session creation request: " << e.what();
>      }
>  }
>  
> -void culs::Skeleton::Private::remove_session(const SessionWrapper::Ptr& session)
> +bool culs::Skeleton::add_to_session_store_for_path(
> +        const core::dbus::types::ObjectPath& path,
> +        const culss::Interface::Ptr& session)
>  {
>      std::lock_guard<std::mutex> lg(guard);
> -    session_store.erase(session->path());
> -
> -    VLOG(1) << "# of session in session store: " << session_store.size() << std::endl;
> +    bool inserted = false;
> +    std::tie(std::ignore, inserted) = session_store.insert(std::make_pair(path, session));
> +    return inserted;
> +}
> +
> +core::Property<bool>& culs::Skeleton::does_satellite_based_positioning()
> +{
> +    return *properties.does_satellite_based_positioning;
> +}
> +
> +core::Property<bool>& culs::Skeleton::does_report_cell_and_wifi_ids()
> +{
> +    return *properties.does_report_cell_and_wifi_ids;
> +}
> +
> +core::Property<bool>& culs::Skeleton::is_online()
> +{
> +    return *properties.is_online;
> +}
> +
> +core::Property<std::map<cul::SpaceVehicle::Key, cul::SpaceVehicle>>& culs::Skeleton::visible_space_vehicles()
> +{
> +    return *properties.visible_space_vehicles;
>  }
> 
> === modified file 'src/location_service/com/ubuntu/location/service/stub.cpp'
> --- src/location_service/com/ubuntu/location/service/stub.cpp	2014-03-05 12:57:39 +0000
> +++ src/location_service/com/ubuntu/location/service/stub.cpp	2014-06-24 16:02:38 +0000
> @@ -15,10 +15,12 @@
>   *
>   * Authored by: Thomas Voß <thomas.voss at canonical.com>
>   */
> -#include "com/ubuntu/location/service/stub.h"
> -#include "com/ubuntu/location/service/session/stub.h"
> -
> -#include "com/ubuntu/location/logging.h"
> +#include <com/ubuntu/location/service/stub.h>
> +#include <com/ubuntu/location/service/session/stub.h>
> +
> +#include <com/ubuntu/location/logging.h>
> +
> +#include <core/dbus/property.h>
>  
>  namespace cul = com::ubuntu::location;
>  namespace culs = com::ubuntu::location::service;
> @@ -28,8 +30,23 @@
>  
>  struct culs::Stub::Private
>  {
> -    core::dbus::Bus::Ptr bus;
> -    core::dbus::Object::Ptr object;
> +    Private(const dbus::Bus::Ptr& connection,
> +            const dbus::Object::Ptr& object)
> +        : bus(connection),
> +          object(object),
> +          does_satellite_based_positioning(object->get_property<culs::Interface::Properties::DoesSatelliteBasedPositioning>()),
> +          does_report_cell_and_wifi_ids(object->get_property<culs::Interface::Properties::DoesReportCellAndWifiIds>()),
> +          is_online(object->get_property<culs::Interface::Properties::IsOnline>()),
> +          visible_space_vehicles(object->get_property<culs::Interface::Properties::VisibleSpaceVehicles>())
> +    {
> +    }
> +
> +    dbus::Bus::Ptr bus;
> +    dbus::Object::Ptr object;
> +    std::shared_ptr<dbus::Property<culs::Interface::Properties::DoesSatelliteBasedPositioning>> does_satellite_based_positioning;
> +    std::shared_ptr<dbus::Property<culs::Interface::Properties::DoesReportCellAndWifiIds>> does_report_cell_and_wifi_ids;
> +    std::shared_ptr<dbus::Property<culs::Interface::Properties::IsOnline>> is_online;
> +    std::shared_ptr<dbus::Property<culs::Interface::Properties::VisibleSpaceVehicles>> visible_space_vehicles;
>  };
>  
>  culs::Stub::Stub(const dbus::Bus::Ptr& connection) : dbus::Stub<culs::Interface>(connection),
> @@ -44,12 +61,35 @@
>  culss::Interface::Ptr culs::Stub::create_session_for_criteria(const cul::Criteria& criteria)
>  {
>      auto op = d->object->transact_method<
> -	culs::Interface::CreateSessionForCriteria,
> -	culs::Interface::CreateSessionForCriteria::ResultType
> -    >(criteria);
> +            culs::Interface::CreateSessionForCriteria,
> +            culs::Interface::CreateSessionForCriteria::ResultType
> +            >(criteria);
>  
>      if (op.is_error())
> -        throw std::runtime_error(op.error().print());
> +    {
> +        std::stringstream ss; ss << __PRETTY_FUNCTION__ << ": " << op.error().print();
> +        throw std::runtime_error(ss.str());
> +    }
>  
>      return culss::Interface::Ptr(new culss::Stub{d->bus, op.value()});
>  }
> +
> +core::Property<bool>& culs::Stub::does_satellite_based_positioning()
> +{
> +    return *d->does_satellite_based_positioning;
> +}
> +
> +core::Property<bool>& culs::Stub::does_report_cell_and_wifi_ids()
> +{
> +    return *d->does_report_cell_and_wifi_ids;
> +}
> +
> +core::Property<bool>& culs::Stub::is_online()
> +{
> +    return *d->is_online;
> +}
> +
> +core::Property<std::map<cul::SpaceVehicle::Key, cul::SpaceVehicle>>& culs::Stub::visible_space_vehicles()
> +{
> +    return *d->visible_space_vehicles;
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/set_name_for_thread.cpp'
> --- src/location_service/com/ubuntu/location/set_name_for_thread.cpp	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/set_name_for_thread.cpp	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include "set_name_for_thread.h"
> +
> +void com::ubuntu::location::set_name_for_thread(std::thread& t, const char* name)
> +{
> +    pthread_setname_np(t.native_handle(), name);
> +}
> 
> === added file 'src/location_service/com/ubuntu/location/set_name_for_thread.h'
> --- src/location_service/com/ubuntu/location/set_name_for_thread.h	1970-01-01 00:00:00 +0000
> +++ src/location_service/com/ubuntu/location/set_name_for_thread.h	2014-06-24 16:02:38 +0000
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright © 2012-2013 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser G


-- 
https://code.launchpad.net/~thomas-voss/location-service/add_controller_and_service_configuration/+merge/204490
Your team Ubuntu Phablet Team is subscribed to branch lp:location-service.



More information about the Ubuntu-reviews mailing list