diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 575d2944b43c08c3a2fb1b7cec1a8b4f926ab172..070da72b3e5e9e8500118456bdd4d5c66c6d5c83 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,8 +1,10 @@
 before_script:
     -  sed -i '/^#\sdeb-src /s/^#//' '/etc/apt/sources.list'
-    - apt-get update && apt-get build-dep --yes geoclue-2.0
-    - apt-get install --yes git gobject-introspection libmm-glib-dev wget libnotify-dev xsltproc gtk-doc-tools python3-pip ninja-build gettext modemmanager-dev
-    - pip3 install meson
+    - apt-get --allow-unauthenticated update && apt-get build-dep --yes geoclue-2.0
+    - apt-get install --yes git gobject-introspection libmm-glib-dev wget
+    - apt-get install --yes libnotify-dev xsltproc gtk-doc-tools python3-pip
+    - apt-get install --yes ninja-build gettext modemmanager-dev
+    - pip3 install meson==0.53.2
 
 # Ubuntu 14.04 is not supported, see README for details
 #
@@ -17,20 +19,20 @@ ubuntu-16.04:
             - "${CI_PROJECT_DIR}/build"
     script: meson -Dgtk-doc=false build && ninja -C build && ninja -C build test && ninja -C build install
 
-ubuntu-17.10:
-    image: ubuntu:artful
+ubuntu-18.04:
+    image: ubuntu:bionic
     artifacts:
         when: always
-        name: "artful-${CI_COMMIT_REF_NAME}"
+        name: "bionic-${CI_COMMIT_REF_NAME}"
         paths:
             - "${CI_PROJECT_DIR}/build"
     script: meson build && ninja -C build && ninja -C build test && ninja -C build install
 
-ubuntu-18.04:
+ubuntu-18.04-no-backend:
     image: ubuntu:bionic
     artifacts:
         when: always
-        name: "bionic-${CI_COMMIT_REF_NAME}"
+        name: "bionic-no-backend-${CI_COMMIT_REF_NAME}"
         paths:
             - "${CI_PROJECT_DIR}/build"
-    script: meson build && ninja -C build && ninja -C build test && ninja -C build install
+    script: meson -Denable-backend=false build && ninja -C build && ninja -C build test && ninja -C build install
diff --git a/HACKING.md b/HACKING.md
new file mode 100644
index 0000000000000000000000000000000000000000..ef63ca020be05f3ca29cb5241c4a1bec53265f6f
--- /dev/null
+++ b/HACKING.md
@@ -0,0 +1,83 @@
+# Building Geoclue
+
+- The following are the dependencies needed to build Geoclue2. But If Geoclue2
+  is already included in your distro/OS, you should be able to use the
+  package manager's command to install all build depedndancies.
+
+  * gio (>= 2.44.0)
+  * gobject-introspection
+  * json-glib
+  * libsoup2.4 (>= 2.42)
+  * pkg-config
+
+  Fedora:
+
+  ```shell
+  sudo dnf builddep geoclue2
+  ```
+
+  Debian and Ubuntu:
+
+  ```shell
+  sudo apt build-dep geoclue-2.0
+  ```
+
+- For a full-fledged build, you also want ModemManager (mm-glib), 
+  avahi-client and avahi-glib. You want the latter two if you want to use the 
+  [geoclue-share app](https://wiki.gnome.org/Apps/GeoclueShare). You also need 
+  libnotify if you want to build the demo agent.
+
+  Fedora:
+
+  ```shell
+  sudo dnf install ModemManager-devel
+  sudo dnf install avahi-devel
+  sudo dnf install avahi-glib-devel
+  sudo dnf install libnotify-devel
+  ```
+
+  Debian and Ubuntu:
+
+  ```shell
+  sudo apt install modemmanager-dev
+  sudo apt install libavahi-client-dev
+  sudo apt install libavahi-glib-dev
+  sudo apt install libnotify-dev
+  ```
+
+- [Install meson](https://mesonbuild.com/Getting-meson.html).
+
+- Ensure you have a `geoclue` user on your system. If it already exists, you may
+  need to modify `/etc/passwd` file to make it a login user account by replacing
+  `/sbin/nologin` with `/bin/bash` (or the path to your preferred shell).
+
+- Build and install geoclue.
+
+  ```shell
+  meson --prefix=/usr --sysconfdir /etc -Ddbus-srv-user=geoclue build
+  # you may need to pass --libdir=/usr/lib64 on some systems (eg. Fedora)
+  ninja -C build
+  sudo ninja -C build install
+  ```
+
+- Then you can run it as:
+
+  ```shell
+  sudo su geoclue # Starts a new shell as `geoclue` user
+  G_MESSAGES_DEBUG=Geoclue /usr/libexec/geoclue
+  ```
+
+  If you get the following error, make sure `geoclue` process is not already
+  running:
+
+  ```
+  > Failed to acquire name 'org.freedesktop.GeoClue2' on system bus or lost it
+  ```
+
+- Now you can test if Geoclue is running and working:
+
+  ```shell
+  /usr/libexec/geoclue-2.0/demos/where-am-i
+  ```
+
+  It will give your current location.
diff --git a/NEWS b/NEWS
index db99b756d36216cd8001df2b496fc3147a8249ab..6b2856da22b3c098e00bccd85c220e4da0b7ce0d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,58 @@
+2.5.7
+=====
+
+Many fixes. Can't bother to list them. You can get the list of changes from git.
+
+
+2.5.6
+=====
+
+- Fix crashes in WiFi handling code.
+- Plug a leak.
+
+Contributors:
+
+Amaury Pouly <amaury.pouly@gmail.com>
+Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
+Will Thompson <will@willthompson.co.uk>
+Zeeshan Ali <zeeshanak@gnome.org>
+
+2.5.5
+=====
+
+- Plug another leak.
+- Fix another buffer overflow.
+- Fix WiFi-geolocation that got broken in 2.5.4.
+- Put freequently used small strings on the stack to avoid excessive memory
+  usage.
+
+2.5.4
+=====
+
+- Plug a leak that becomes pretty huge after a while of running Geoclue.
+- Fix a buffer-overflow.
+
+2.5.3
+=====
+
+- Fix a crash.
+- Support for GGA messages from more NMEA sources.
+- New API to allow automatic server side deletion of client.
+- Automatically delete client on server when using GClueSimple.
+- Avoid linking to system-installed library.
+- Fix library-only build.
+- Add manpage for geoclue.conf file.
+- Document usage and building of the project.
+- Other fixes and improvements.
+
+Contributors:
+
+Benjamin Berg <bberg@redhat.com>
+Inzamam <inzamam.15@cse.mrt.ac.lk>
+Sachin Chand <schand1997@gmail.com>
+Sumera Priyadarsini <sylphrenadin@gmail.com>
+Zeeshan Ali <zeeshanak@gnome.org>
+
 2.5.2
 =====
 
diff --git a/README b/README
deleted file mode 100644
index b7bb15581f5e5ef6283710d018041185acbe20d7..0000000000000000000000000000000000000000
--- a/README
+++ /dev/null
@@ -1,14 +0,0 @@
-GeoClue: The Geoinformation Service
-===================================
-
-GeoClue is a D-Bus geoinformation service. The goal of the Geoclue project is to
-make creating location-aware applications as simple as possible.
-
-Geoclue is Free Software, licensed under GNU GPLv2+.
-
-# Troubleshooting and known limitations
-
-  * GeoClue requires Glib >= 2.44.0 which should make it hard to build to Ubuntu
-14.04. It's currently not supported, but all maintained Ubuntu versions >= 16.04
-are.
-
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0ea9657b230df4f32d279951487037190cd5488b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,74 @@
+Geoclue: The Geoinformation Service
+===================================
+
+Geoclue is a D-Bus geoinformation service. The goal of the Geoclue project
+is to make creating location-aware applications as simple as possible.
+
+Geoclue is Free Software, licensed under GNU GPLv2+.
+
+Geoclue comprises the following functionalities : 
+- WiFi-based geolocation (accuracy: in meters)
+- GPS(A) receivers (accuracy: in centimeters)
+- GPS of other devices on the local network, e.g smartphones (accuracy: 
+  in centimeters)
+- 3G modems (accuracy: in kilometers, unless modem has GPS)
+- GeoIP (accuracy: city-level)
+
+WiFi-based geolocation makes use of 
+[Mozilla Location Service](https://wiki.mozilla.org/CloudServices/Location). 
+
+If geoclue is unable to find you, you can easily fix that by installing 
+and running a 
+[simple app](https://wiki.mozilla.org/CloudServices/Location#Contributing) on 
+your phone. For using phone GPS, you'll need to install the latest version of 
+[GeoclueShare app](https://github.com/ankitstarski/GeoclueShare/releases)
+on your phone (currently, this is supported only on Android devices).
+
+Geoclue was also used for (reverse-)geocoding but that functionality has 
+been dropped in favour of the 
+[geocode-glib library](http://ftp.gnome.org/pub/GNOME/sources/geocode-glib/).
+
+# History
+Geoclue was started during the GNOME Summit 2006 in Boston. At least 
+Keith Preston and Tuomas Kuosmanen can be blamed. There was a total rewrite 
+after version 0.9. 
+
+Use tag "0.9" (as in git checkout 0.9) if you need the old code.
+
+There was yet another rewrite that we call geoclue2. The first version to 
+introduce the re-write was version 1.99.
+
+# Communication and Contribution
+
+- Discussions take place on the 
+[GNOME Discourse](https://discourse.gnome.org/c/platform).
+- The IRC chat for geoclue is on __#gnome-maps__ at irc.gimp.org .
+- Issues are tracked on 
+[Gitlab](https://gitlab.freedesktop.org/geoclue/geoclue/issues).
+
+# Get Source Code
+The source code is available as a tar-ball and in a Git repository.
+
+For latest release tarballs, use the `Download` option of Gitlab on the 
+[tag of your choice](https://gitlab.freedesktop.org/geoclue/geoclue/tags/).
+
+Older (than 2.4.13) releases are available 
+[here](http://www.freedesktop.org/software/geoclue/releases/2.4/).
+
+Git repository for Geoclue: https://gitlab.freedesktop.org/geoclue/geoclue
+  
+# Building Geoclue
+
+The guidelines for building geoclue have been documented 
+[here](https://gitlab.freedesktop.org/geoclue/geoclue/blob/master/HACKING.md). 
+
+# Using Geoclue in an application
+ 
+- __D-Bus API__: The documentation for using geoclue with D-Bus API is 
+[here](http://www.freedesktop.org/software/geoclue/docs/).
+- __Libgeoclue API documentation__:  The documentation is available 
+[here](https://www.freedesktop.org/software/geoclue/docs/libgeoclue/).
+- __C user application__: 
+[Here](https://gitlab.freedesktop.org/geoclue/geoclue/blob/master/demo/where-am-i.c)
+is an example showing a C application that uses 
+geoclue to locate its user. 
diff --git a/data/geoclue.5.in b/data/geoclue.5.in
new file mode 100644
index 0000000000000000000000000000000000000000..b6a5795546269cd19323dc7f5c3b7f0c03588039
--- /dev/null
+++ b/data/geoclue.5.in
@@ -0,0 +1,171 @@
+.TH "GEOCLUE CONFIGURATION" 5 
+.SH NAME
+geoclue.conf
+\-
+geoclue configuration parameters
+.SH SYNOPSIS
+.B @sysconfdir@/geoclue/geoclue.conf
+.SH DESCRIPTION
+.ad
+.fi
+The geoclue geoclue.conf configuration file specifies parameters that
+control the operation of geoclue.
+.PP
+All configurations settings below are mandatory and the defaults are
+what you see before you edit them in geoclue.conf. If you want to keep the default
+values around, copy and comment out the appropriate line(s) before
+changing them.
+.SH AGENT CONFIGURATION OPTIONS
+.B \fI[agent]
+is used to begin the agent configuration.
+.IP \fBwhitelist 
+.br
+Whitelist of desktop IDs (without .desktop part) of all agents we recognise,
+separated by a ';'.
+.IP 
+.B whitelist=geoclue-demo-agent;gnome-shell;io.elementary.desktop.agent-geoclue2
+.br
+.IP \fB[network-nmea]
+.br
+Network NMEA source configuration options
+.IP
+.B \fBenable=true 
+.br
+Fetch location from NMEA sources on local network?
+.br
+.IP \fB[3G]
+.br
+3G source configuration options
+.IP
+.B \fBenable=true 
+.br
+Enable 3G source
+.br
+.IP \fB[cdma]
+.br
+CDMA source configuration options
+.IP
+.B \fBenable=true 
+.br
+Enable CDMA source
+.br
+.IP \fB[modem-gps]
+.br
+Modem GPS source configuration options
+.IP
+.B \fBenable=true 
+.br
+Enable Modem-GPS source
+.br
+.IP \fB[wifi]
+.br
+WiFi source configuration options
+.IP
+.B \fBenable=true 
+.br
+Enable WiFi source
+.IP
+.B url=\fIhttps://location.services.mozilla.com/v1/geolocate?key=geoclue
+.br
+URL to the wifi geolocation service. The key can currenty be anything, just
+needs to be present but that is likely going to change in future.
+.IP
+.B submit-data=false
+Submit data to Mozilla Location Service
+.br
+If set to true, geoclue will automatically submit network data to Mozilla
+each time it gets a GPS lock.
+.IP
+.B submission-url=\fIhttps://location.services.mozilla.com/v1/submit?key=geoclue
+.br
+URL to submission API of Mozilla Location Service
+.IP
+.B submission-nick=geoclue
+.br
+A nickname to submit network data with. A nickname must be 2-32 characters long.
+.br
+.SH APPLICATION CONFIGURATION OPTIONS
+Having an entry here for an application with 
+.B allowed=true
+means that geoclue will not ask agent to authorize the application. This is to
+ensure that applications with built-in authorization mechanism (e.g web
+browsers) do not have to be bound to agents.
+.PP
+If your application is denied access to location information and your
+operating system doesn't provide any mechanism to change that, it is
+likely a bug in your operation system (or geoclue). The solution is to
+report the issue with all details, rather than adding your application
+to this list.
+.IP Format:
+.RS
+.B [random-app]
+.br
+Desktop ID of application without .desktop part
+.PP
+.B allowed=true|false
+.br
+Allowed access to location information?
+.PP
+.B system=true|false
+.br
+Is application a system component?
+.PP
+.B users=
+.br
+List of UIDs of all users for which this application is allowed location
+info access, separate by ';'. Keep it empty for allowing it for all users.
+.RE
+.IP Examples:
+.RS
+.B [gnome-datetime-panel]
+.br
+allowed=true
+.br
+system=true
+.br
+users=
+.PP
+.B [gnome-color-panel]
+.br
+allowed=true
+.br
+system=true
+.br
+users=
+.PP
+.B [org.gnome.Shell]
+.br
+allowed=true
+.br
+system=true
+.br
+users=
+.PP
+.B [io.elementary.desktop.agent-geoclue2]
+.br
+allowed=true
+.br
+system=true
+.br
+users=
+.PP
+.B [epiphany]
+.br
+allowed=true
+.br
+system=false
+.br
+users=
+.PP
+.B [firefox]
+.br
+allowed=true
+.br
+system=false
+.br
+users=
+.br
+.SH AUTHOR
+.na
+.nf
+Sachin Chand
diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in
index 4b5b972aaeca10b4938ef5ac6f4a8e2d9c825c43..fb111de59a05ff7f50a40055844db8edbae22744 100644
--- a/data/geoclue.conf.in
+++ b/data/geoclue.conf.in
@@ -66,18 +66,15 @@ submit-data=false
 # URL to submission API of Mozilla Location Service
 submission-url=https://location.services.mozilla.com/v1/submit?key=geoclue
 
-# A nickname to submit network data with. This is currently used for leaderboard:
-# https://location.services.mozilla.com/leaders
-# A nickname must be 2-32 characters long.
+# A nickname to submit network data with. A nickname must be 2-32 characters long.
 submission-nick=geoclue
 
 # Application configuration options
 #
 # NOTE: Having an entry here for an application with allowed=true means that
 #       geoclue will not ask agent to authorize the application. This is to
-#       ensure that system components and applications with built-in
-#       authorization mechanism (e.g web browsers) do not have to be bound to
-#       agents.
+#       ensure that applications with built-in authorization mechanism (e.g web
+#       browsers) do not have to be bound to agents.
 #
 #       If your application is denied access to location information and your
 #       operating system doesn't provide any mechanism to change that, it is
diff --git a/data/meson.build b/data/meson.build
index f82686473c01888b18e0bad9930d3f22052db2ed..c189753a60171c0cc5d45013f95a92409553a6b1 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -16,6 +16,7 @@ if get_option('enable-backend')
     conf = configuration_data()
     conf.set('libexecdir', libexecdir)
     conf.set('dbus_srv_user', get_option('dbus-srv-user'))
+    conf.set('sysconfdir', sysconfdir)
 
     service_dir = join_paths(datadir, 'dbus-1', 'system-services')
     configure_file(output: 'org.freedesktop.GeoClue2.service',
@@ -23,6 +24,12 @@ if get_option('enable-backend')
                    configuration: conf,
                    install_dir: service_dir)
 
+    man_file = configure_file(output: 'geoclue.5',
+                              input: 'geoclue.5.in',
+                              configuration: conf)
+
+    install_man(man_file)
+
     # DBus Service policy file
     dbus_service_dir = get_option('dbus-sys-dir')
     if dbus_service_dir == ''
diff --git a/debian/changelog b/debian/changelog
index 1c09f9959fdd09052259991970be5c99983d5b87..642927720418cd8821608c01d552bb938d70ba8b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,26 +1,100 @@
-geoclue-2.0 (2.5.2-1+deb10u1co0) apertis; urgency=medium
+geoclue-2.0 (2.5.7-2apertis0) apertis; urgency=medium
 
-  * Sync from Debian debian/buster.
+  * Sync from Debian debian/bullseye.
 
- -- Apertis CI <devel@lists.apertis.org>  Mon, 22 Feb 2021 07:47:20 +0000
+ -- Apertis CI <devel@lists.apertis.org>  Fri, 12 Mar 2021 00:09:19 +0000
+
+geoclue-2.0 (2.5.7-2) unstable; urgency=medium
 
-geoclue-2.0 (2.5.2-1+deb10u1) buster; urgency=medium
+  * d/p/fix-nowifi-query.patch: Fix getting a location if the computer has no
+    wifi card (Closes: #978437)
 
+ -- Laurent Bigonville <bigon@debian.org>  Thu, 31 Dec 2020 04:46:07 +0100
+
+geoclue-2.0 (2.5.7-1) unstable; urgency=medium
+
+  [ Laurent Bigonville ]
+  * New upstream version 2.5.7
+    - Check the maximum allowed accuracy level even for system applications.
+      Respect the value of the user preference concerning the usage of their
+      geolocation. This should fix the privacy and GDPR conformity concerns as
+      the user explicitly needs to enable the option.
+      Note that there is no distinction between the system applications
+      anymore, turning on the option is allowing them all to get the location.
+      (Closes: #924516, #958497)
   * debian/README.Debian: Add information about MLS and a link to the service
     Privacy Notice page
-  * Check the maximum allowed accuracy level even for system applications.
-    Respect the value of the user preference concerning the usage of their
-    geolocation. This should fix the privacy and GDPR conformity concerns as
-    the user explicitly needs to enable the option.
-    Note that there is no distinction between the system applications
-    anymore, turning on the option is allowing them all to get the location.
-    (Closes: #924516, #958497)
+  * Add debian/salsa-ci.yml file
+  * debian/control: Remove Craig Andrews from the Uploaders.
+    He has not been active since 2009, thanks for his previous work on the
+    package
   * d/p/: Add a patch to make the Mozilla API key configurable
   * debian/rules: Use the key that has been allocated to debian for MLS queries
+  * d/gbp.conf: Stop adding the commit-id and set multimaint-merge to True
+  * debian/control: Bump Standards-Version to 4.5.1 (no further changes)
   * d/p: Add an upstream patch to fix the display of the usage indicator
-  * Fix crash if submission-url is not set in the config, patch from upstream
+  * d/p: Remove the remaining differences between system app and flatpak ones.
+    This fix an issue when geoclue is D-Bus activated by a client and also
+    make sure that a running client is disconnected when the user disables
+    the location services (set the accuracy to 0)
+
+  [ Chris McGee ]
+  * debian/control: Add rules requires root
+
+  [ Debian Janitor ]
+  * Refer to specific version of license LGPL-2+.
+  * Apply multi-arch hints.
+    + geoclue-doc, libgeoclue-doc: Add Multi-Arch: foreign.
+
+ -- Laurent Bigonville <bigon@debian.org>  Fri, 25 Dec 2020 14:59:35 +0100
+
+geoclue-2.0 (2.5.6-1) unstable; urgency=medium
+
+  [ Debian Janitor ]
+  * [99359d91] Bump debhelper from old 11 to 12.
+  * [f9dd0d99] Set debhelper-compat version in Build-Depends.
+  * [a0d0042a] debian/copyright: use spaces rather than tabs to start
+    continuation lines.
+  * [32c230e4] Set upstream metadata fields: Repository, Repository-Browse.
+  * [3a2f4acf] Drop unnecessary dependency on dh-autoreconf.
+
+  [ Laurent Bigonville ]
+  * [ae0a90ea] debian/control: Bump Standards-Version to 4.5.0 (no further
+    changes)
 
- -- Laurent Bigonville <bigon@debian.org>  Fri, 25 Dec 2020 17:19:50 +0100
+  [ Will Thompson ]
+  * [d2643a89] New upstream version 2.5.6
+
+ -- Laurent Bigonville <bigon@debian.org>  Sun, 08 Mar 2020 17:06:02 +0100
+
+geoclue-2.0 (2.5.5-1) unstable; urgency=medium
+
+  * [b4cfe4e7] debian/rules: Install the NEWS file as upstream changelog
+  * [3d876ed8] New upstream version 2.5.5
+  * [29ba01cf] Set libexecdir to /usr/libexec now that the policy allows it
+
+ -- Laurent Bigonville <bigon@debian.org>  Wed, 02 Oct 2019 13:20:41 +0200
+
+geoclue-2.0 (2.5.3-1) unstable; urgency=medium
+
+  * [48856ed2] New upstream version 2.5.3
+  * [1bf75efb] debian/control: Bump Standards-Version to 4.4.0 (no further
+    changes)
+  * [9e941a46] debian/libgeoclue-2-0.symbols: Add newly exported symbols
+  * [158dae34] debian/geoclue-2.0.install: Install new geoclue.5 manpage
+  * [f0c2f253] debian/copyright: Use https for the format uri, to please lintian
+  * [80a3663a] debian/copyright: Removed unused file paragraph
+  * [ed125085] debian/geoclue-2.0.lintian-overrides: Override
+    package-supports-alternative-init-but-no-init.d-script. The daemon is
+    D-Bus activated, not started at boot
+
+ -- Laurent Bigonville <bigon@debian.org>  Thu, 11 Jul 2019 13:53:11 +0200
+
+geoclue-2.0 (2.5.2-1+deb10u1co0) apertis; urgency=medium
+
+  * Sync from Debian debian/buster.
+
+ -- Apertis CI <devel@lists.apertis.org>  Mon, 22 Feb 2021 07:47:20 +0000
 
 geoclue-2.0 (2.5.2-1co1) apertis; urgency=medium
 
@@ -509,7 +583,7 @@ geoclue (0.11.1-1.1) unstable; urgency=low
   * Non-maintainer upload.
   * Adding quilt patch system and a patch to fix a FTBFS due to a changed
     API of libgammu (Closes: #518586). Also adding debian/README.source
-    as required by policy. 
+    as required by policy.
 
  -- Bernd Zeimetz <bzed@debian.org>  Wed, 25 Mar 2009 20:20:54 +0100
 
@@ -539,7 +613,6 @@ geoclue (0.2svn20070715-1) unstable; urgency=low
 
 geoclue (0.2svn20070704-1) unstable; urgency=low
 
-  * Initial release 
+  * Initial release
 
  -- Jussi Kukkonen <jhkukkon@cc.hut.fi>  Wed, 04 Jul 2007 11:27:36 +0300
-
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index b4de3947675361a7770d29b8982c407b0ec6b2a0..0000000000000000000000000000000000000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-11
diff --git a/debian/control b/debian/control
index 8fb6754e40206fe5de6cfe86ea9cb1719ab97121..5b702b7ad50bbf2c0d8bbec24a74d074aa33702f 100644
--- a/debian/control
+++ b/debian/control
@@ -2,8 +2,7 @@ Source: geoclue-2.0
 Section: utils
 Priority: optional
 Maintainer: Laurent Bigonville <bigon@debian.org>
-Uploaders: Craig Andrews <candrews@integralblue.com>
-Build-Depends: debhelper (>= 11),
+Build-Depends: debhelper-compat (= 12),
                gobject-introspection (>= 0.9.6),
                intltool (>= 0.40.0),
                libavahi-client-dev (>= 0.6.10),
@@ -19,9 +18,10 @@ Build-Depends: debhelper (>= 11),
                valac
 Build-Depends-Indep: gtk-doc-tools <!nodoc>, libglib2.0-doc <!nodoc>
 Homepage: https://gitlab.freedesktop.org/geoclue/geoclue/wikis/home
-Standards-Version: 4.3.0
+Standards-Version: 4.5.1
 Vcs-Git: https://salsa.debian.org/freedesktop-team/geoclue-2.0.git
 Vcs-Browser: https://salsa.debian.org/freedesktop-team/geoclue-2.0
+Rules-Requires-Root: no
 
 Package: geoclue-2.0
 Architecture: any
@@ -54,6 +54,7 @@ Architecture: all
 Section: doc
 Depends: ${misc:Depends}
 Build-Profiles: <!nodoc>
+Multi-Arch: foreign
 Description: geoinformation service (D-Bus API documentation)
  GeoClue is a D-Bus geoinformation service. The goal of the Geoclue project
  is to make creating location-aware applications as simple as possible.
@@ -103,6 +104,7 @@ Architecture: all
 Section: doc
 Depends: ${misc:Depends}
 Build-Profiles: <!nodoc>
+Multi-Arch: foreign
 Description: convenience library to interact with geoinformation service (API documentation)
  GeoClue is a D-Bus geoinformation service. The goal of the Geoclue project
  is to make creating location-aware applications as simple as possible.
diff --git a/debian/copyright b/debian/copyright
index 3bfa51748a64503aa6547e87f99610566b456afa..da392d71e17e38cbc222ea0c54bdb002520bad83 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,4 +1,4 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 Upstream-Name: GeoClue
 Source: http://www.freedesktop.org/wiki/Software/GeoClue/
 
@@ -27,11 +27,6 @@ License: GPL-2+
  License version 2 can be found in the file
  `/usr/share/common-licenses/GPL-2'.
 
-Files: src/geocode-glib/*
-Copyright: Copyright (C) 2011-2012 Bastien Nocera
-           Copyright (C) 2013 Jonas Danielsson
-License: LGPL-2+
-
 Files: docs/geoclue-docs.xml
 Copyright: Copyright (C) 2013 Red Hat, Inc.
 License: GFDL-NIV-1.1+
@@ -52,7 +47,7 @@ License: GFDL-NIV-1.1+
 Files: debian/*
 Copyright: Copyright 2007 Jussi Kukkonen <jhkukkon@cc.hut.fi>
            Copyright 2007 Craig Andrews <candrews@integralblue.com>
-	   Copyright 2013 Andreas Henriksson <andreas@fatal.se>
+           Copyright 2013 Andreas Henriksson <andreas@fatal.se>
 License: LGPL-2+
 
 License: LGPL-2+
@@ -72,4 +67,4 @@ License: LGPL-2+
  02110-1301, USA
  .
  On Debian systems, the complete text of the GNU Lesser General
- Public License can be found in `/usr/share/common-licenses/LGPL'.
+ Public License can be found in `/usr/share/common-licenses/LGPL-2'.
diff --git a/debian/gbp.conf b/debian/gbp.conf
index 1de1e59ccb511297d5870f2b634d297ac06bfd4b..5eda4134dbb25e65a0dff4ce1ae0546dc8f6c4fd 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,21 +1,12 @@
 # Configuration file for git-buildpackage and friends
 
 [DEFAULT]
-upstream-tag = upstream/%(version)s
-debian-tag = debian/%(version)s
 pristine-tar = True
-debian-branch = master
-upstream-branch = upstream
 
 # Options only affecting git-buildpackage
 [buildpackage]
 sign-tags = True
-tarball-dir = ../tarballs/
-export-dir = ../build-area/
 
 # Options only affecting git-dch
 [dch]
-id-length = 8
-meta = True
-meta-closes = Closes|LP
-
+multimaint-merge = True
diff --git a/debian/geoclue-2-demo.install b/debian/geoclue-2-demo.install
index 75bbff06683acdee113a90d7fd3f005c68ac3a73..cda6a13383ae74bf1d4dee380ebe78dea6cf219f 100644
--- a/debian/geoclue-2-demo.install
+++ b/debian/geoclue-2-demo.install
@@ -1,2 +1,2 @@
-usr/lib/geoclue-2.0/demos/where-am-i
+usr/libexec/geoclue-2.0/demos/where-am-i
 usr/share/applications/geoclue-where-am-i.desktop
diff --git a/debian/geoclue-2.0.install b/debian/geoclue-2.0.install
index 40637f97a98b00d430c780ab534f6eb83f9683c1..a0b40fec254defd6dcc1e48f978938c2d0c6dff1 100644
--- a/debian/geoclue-2.0.install
+++ b/debian/geoclue-2.0.install
@@ -5,8 +5,9 @@ etc/geoclue/
 etc/xdg/autostart/geoclue-demo-agent.desktop
 lib/systemd/system/
 usr/lib/*/pkgconfig/geoclue-2.0.pc
-usr/lib/geoclue-2.0/demos/agent
-usr/lib/geoclue-2.0/geoclue
+usr/libexec/geoclue-2.0/demos/agent
+usr/libexec/geoclue
 usr/share/applications/geoclue-demo-agent.desktop
 usr/share/dbus-1/interfaces/
 usr/share/dbus-1/system-services/
+usr/share/man/man5/geoclue.5
diff --git a/debian/geoclue-2.0.lintian-overrides b/debian/geoclue-2.0.lintian-overrides
index 208c9f85fc5b2ece2f955a9ee2e276c08572d60b..f08d829d678f7785a18e65620e883909796cbb5c 100644
--- a/debian/geoclue-2.0.lintian-overrides
+++ b/debian/geoclue-2.0.lintian-overrides
@@ -1,3 +1,5 @@
 # This is not completely fixed but we have mitigated the issue by only allowing
 # the geoclue user to call these methods
 geoclue-2.0: dbus-policy-excessively-broad etc/dbus-1/system.d/org.freedesktop.GeoClue2.Agent.conf <policy user="geoclue"><allow send_interface="org.freedesktop.DBus.Properties" send_path="/org/freedesktop/GeoClue2/Agent"/>
+# The daemon is D-Bus activated, not started at boot
+geoclue-2.0: package-supports-alternative-init-but-no-init.d-script lib/systemd/system/geoclue.service
diff --git a/debian/libgeoclue-2-0.symbols b/debian/libgeoclue-2-0.symbols
index a6c14e02bee30cc3aedb5305973351bd0cdb3c67..5a4b69bb015ddf03fdd079fe7e95a57a7282bddb 100644
--- a/debian/libgeoclue-2-0.symbols
+++ b/debian/libgeoclue-2-0.symbols
@@ -24,6 +24,10 @@ libgeoclue-2.so.0 libgeoclue-2-0 #MINVER#
  gclue_client_override_properties@Base 2.4.0
  gclue_client_proxy_create@Base 2.4.0
  gclue_client_proxy_create_finish@Base 2.4.0
+ gclue_client_proxy_create_flags_get_type@Base 2.5.3
+ gclue_client_proxy_create_full@Base 2.5.3
+ gclue_client_proxy_create_full_finish@Base 2.5.3
+ gclue_client_proxy_create_full_sync@Base 2.5.3
  gclue_client_proxy_create_sync@Base 2.4.0
  gclue_client_proxy_get_type@Base 2.4.0
  gclue_client_proxy_new@Base 2.4.0
diff --git a/debian/patches/0001-service-Check-the-maximum-allowed-accuracy-level-eve.patch b/debian/patches/0001-service-Check-the-maximum-allowed-accuracy-level-eve.patch
deleted file mode 100644
index f4183d8fd0dd9b433afe5810029a373e133fa963..0000000000000000000000000000000000000000
--- a/debian/patches/0001-service-Check-the-maximum-allowed-accuracy-level-eve.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From: Laurent Bigonville <bigon@bigon.be>
-Date: Fri, 23 Oct 2020 21:37:12 +0200
-Subject: service: Check the maximum allowed accuracy level even for system
- apps
-
-We need to check the maximum allowed accuracy even for system apps
-otherwise the user cannot disable the geolocalization for these
-(max_accuracy set to 0)
-
-Fix: https://gitlab.freedesktop.org/geoclue/geoclue/-/issues/111
----
- src/gclue-service-client.c | 16 +++++-----------
- 1 file changed, 5 insertions(+), 11 deletions(-)
-
-diff --git a/src/gclue-service-client.c b/src/gclue-service-client.c
-index 247fdb6..62ea932 100644
---- a/src/gclue-service-client.c
-+++ b/src/gclue-service-client.c
-@@ -447,6 +447,7 @@ handle_post_agent_check_auth (StartData *data)
-         GClueConfig *config;
-         GClueAppPerm app_perm;
-         guint32 uid;
-+        gboolean system_app;
- 
-         uid = gclue_client_info_get_user_id (priv->client_info);
-         max_accuracy = gclue_agent_get_max_accuracy_level (priv->agent_proxy);
-@@ -471,8 +472,11 @@ handle_post_agent_check_auth (StartData *data)
-         app_perm = gclue_config_get_app_perm (config,
-                                               data->desktop_id,
-                                               priv->client_info);
-+        system_app = (gclue_client_info_get_xdg_id (priv->client_info) == NULL);
- 
--        if (app_perm == GCLUE_APP_PERM_ALLOWED) {
-+        if (app_perm == GCLUE_APP_PERM_ALLOWED || system_app) {
-+                /* Since we have no reliable way to identify system apps, no
-+                 * need for auth for them. */
-                 complete_start (data);
-                 return;
-         }
-@@ -556,7 +560,6 @@ gclue_service_client_handle_start (GClueDBusClient       *client,
-         const char *desktop_id;
-         GClueAppPerm app_perm;
-         guint32 uid;
--        gboolean system_app = FALSE;
- 
-         if (priv->locator != NULL) {
-                 /* Already started */
-@@ -569,7 +572,6 @@ gclue_service_client_handle_start (GClueDBusClient       *client,
-         if (desktop_id == NULL) {
-                 /* Non-xdg app */
-                 desktop_id = gclue_dbus_client_get_desktop_id (client);
--                system_app = TRUE;
-         }
- 
-         if (desktop_id == NULL) {
-@@ -605,14 +607,6 @@ gclue_service_client_handle_start (GClueDBusClient       *client,
-         data->accuracy_level = ensure_valid_accuracy_level
-                 (data->accuracy_level, GCLUE_ACCURACY_LEVEL_EXACT);
- 
--        if (system_app) {
--                /* Since we have no reliable way to identify system apps, no
--                 * need for auth for them. */
--                complete_start (data);
--
--                return TRUE;
--        }
--
-         /* No agent == No authorization */
-         if (priv->agent_proxy == NULL) {
-                 /* Already a pending Start()? Denied! */
diff --git a/debian/patches/0002-config-Make-the-Mozilla-API-key-configurable.patch b/debian/patches/0002-config-Make-the-Mozilla-API-key-configurable.patch
index d4a8c8c269e7d0c1e600ad9993c94978b2f65084..8e7cf32ff1067a8a19ac4730fd052a1ef03ed920 100644
--- a/debian/patches/0002-config-Make-the-Mozilla-API-key-configurable.patch
+++ b/debian/patches/0002-config-Make-the-Mozilla-API-key-configurable.patch
@@ -10,6 +10,8 @@ And do not expose it in the configuration file.
  src/gclue-config.c   |  4 ++--
  4 files changed, 16 insertions(+), 10 deletions(-)
 
+diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in
+index fb111de..bebe471 100644
 --- a/data/geoclue.conf.in
 +++ b/data/geoclue.conf.in
 @@ -42,13 +42,13 @@ enable=true
@@ -32,7 +34,7 @@ And do not expose it in the configuration file.
  #
  # WARNING: Please make sure that you are complying with the Google's ToS and
  #          policies if you uncomment this:
-@@ -63,8 +63,10 @@ url=https://location.services.mozilla.co
+@@ -63,8 +63,10 @@ url=https://location.services.mozilla.com/v1/geolocate?key=geoclue
  #
  submit-data=false
  
@@ -43,11 +45,13 @@ And do not expose it in the configuration file.
 +# while changing YOUR_KEY to your MLS API key.
 +#submission-url=https://location.services.mozilla.com/v1/submit?key=YOUR_KEY
  
- # A nickname to submit network data with. This is currently used for leaderboard:
- # https://location.services.mozilla.com/leaders
+ # A nickname to submit network data with. A nickname must be 2-32 characters long.
+ submission-nick=geoclue
+diff --git a/meson.build b/meson.build
+index 088b651..fc41751 100644
 --- a/meson.build
 +++ b/meson.build
-@@ -30,6 +30,7 @@ conf.set_quoted('PACKAGE_BUGREPORT', 'ht
+@@ -30,6 +30,7 @@ conf.set_quoted('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/geoclue/geo
  conf.set_quoted('TEST_SRCDIR', meson.source_root() + '/data/')
  conf.set_quoted('LOCALEDIR', localedir)
  conf.set_quoted('SYSCONFDIR', sysconfdir)
@@ -55,6 +59,8 @@ And do not expose it in the configuration file.
  conf.set10('GCLUE_USE_3G_SOURCE', get_option('3g-source'))
  conf.set10('GCLUE_USE_CDMA_SOURCE', get_option('cdma-source'))
  conf.set10('GCLUE_USE_MODEM_GPS_SOURCE', get_option('modem-gps-source'))
+diff --git a/meson_options.txt b/meson_options.txt
+index 83bc60e..f5d42e3 100644
 --- a/meson_options.txt
 +++ b/meson_options.txt
 @@ -34,3 +34,6 @@ option('systemd-system-unit-dir',
@@ -64,9 +70,11 @@ And do not expose it in the configuration file.
 +option('mozilla-api-key',
 +       type: 'string', value: 'geoclue',
 +       description: 'Your API key for Mozilla Location Service')
+diff --git a/src/gclue-config.c b/src/gclue-config.c
+index 0714d01..76222ff 100644
 --- a/src/gclue-config.c
 +++ b/src/gclue-config.c
-@@ -216,8 +216,8 @@ load_enable_source_config (GClueConfig *
+@@ -216,8 +216,8 @@ load_enable_source_config (GClueConfig *config,
          return enable;
  }
  
diff --git a/debian/patches/0003-Revert-Fixed-hang-on-startup-when-client-app-is-a-sy.patch b/debian/patches/0003-Revert-Fixed-hang-on-startup-when-client-app-is-a-sy.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b1fb101172a36a45bc8c6990c5b5f77b4eb73637
--- /dev/null
+++ b/debian/patches/0003-Revert-Fixed-hang-on-startup-when-client-app-is-a-sy.patch
@@ -0,0 +1,39 @@
+From: Laurent Bigonville <bigon@bigon.be>
+Date: Fri, 25 Dec 2020 13:55:44 +0100
+Subject: Revert "Fixed hang on startup when client app is a system app: avoid
+ wasting 20s waiting on agent."
+
+Now that we are requesting the allowed accuracy from the agent again for
+the system apps, we need to be sure the agent is started and connected
+before denying the request.
+
+This reverts commit 57efed15b09c5c78891f6fa1bfe5a7aee64a8fb8.
+
+Fixes: #139
+---
+ src/gclue-service-manager.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/src/gclue-service-manager.c b/src/gclue-service-manager.c
+index 849debd..020c2af 100644
+--- a/src/gclue-service-manager.c
++++ b/src/gclue-service-manager.c
+@@ -271,7 +271,6 @@ on_client_info_new_ready (GObject      *source_object,
+         GError *error = NULL;
+         guint32 user_id;
+         gint64 now;
+-        gboolean system_app;
+ 
+         info = gclue_client_info_new_finish (res, &error);
+         if (info == NULL) {
+@@ -291,10 +290,7 @@ on_client_info_new_ready (GObject      *source_object,
+         agent_proxy = g_hash_table_lookup (priv->agents,
+                                            GINT_TO_POINTER (user_id));
+         now = g_get_monotonic_time ();
+-
+-        system_app = (gclue_client_info_get_xdg_id (info) == NULL);
+         if (agent_proxy == NULL &&
+-            !system_app &&
+             now < (priv->init_time + AGENT_WAIT_TIMEOUT_USEC)) {
+                 /* Its possible that geoclue was just launched on GetClient
+                  * call, in which case agents need some time to register
diff --git a/debian/patches/0004-service-Stop-the-client-for-system-applications-when.patch b/debian/patches/0004-service-Stop-the-client-for-system-applications-when.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d79ab475d12eb7b1a05b3ffd9ee8677ceeb9fef5
--- /dev/null
+++ b/debian/patches/0004-service-Stop-the-client-for-system-applications-when.patch
@@ -0,0 +1,43 @@
+From: Laurent Bigonville <bigon@bigon.be>
+Date: Fri, 25 Dec 2020 14:13:05 +0100
+Subject: service: Stop the client for system applications when accuracy is
+ set to 0
+
+Now that the accuracy set by the agent is used again for system
+applications, we should again stop the client when the accuracy is set
+to 0
+---
+ src/gclue-service-client.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/src/gclue-service-client.c b/src/gclue-service-client.c
+index 62ea932..3e68f55 100644
+--- a/src/gclue-service-client.c
++++ b/src/gclue-service-client.c
+@@ -330,7 +330,6 @@ on_agent_props_changed (GDBusProxy *agent_proxy,
+         while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
+                 GClueAccuracyLevel max_accuracy;
+                 const char *id;
+-                gboolean system_app;
+ 
+                 if (strcmp (key, "MaxAccuracyLevel") != 0)
+                         continue;
+@@ -338,8 +337,6 @@ on_agent_props_changed (GDBusProxy *agent_proxy,
+                 gdbus_client = GCLUE_DBUS_CLIENT (client);
+                 id = gclue_dbus_client_get_desktop_id (gdbus_client);
+                 max_accuracy = g_variant_get_uint32 (value);
+-                system_app = (gclue_client_info_get_xdg_id
+-                              (client->priv->client_info) == NULL);
+                 /* FIXME: We should be handling all values of max accuracy
+                  *        level here, not just 0 and non-0.
+                  */
+@@ -354,8 +351,7 @@ on_agent_props_changed (GDBusProxy *agent_proxy,
+                         start_client (client, accuracy);
+                         g_debug ("Re-started '%s'.", id);
+                 } else if (max_accuracy == 0 &&
+-                           gclue_dbus_client_get_active (gdbus_client) &&
+-                           !system_app) {
++                           gclue_dbus_client_get_active (gdbus_client)) {
+                         stop_client (client);
+                         client->priv->agent_stopped = TRUE;
+                         g_debug ("Stopped '%s'.", id);
diff --git a/debian/patches/0005-config-Clear-error-after-submission-URL-lookup-fails.patch b/debian/patches/0005-config-Clear-error-after-submission-URL-lookup-fails.patch
deleted file mode 100644
index a438ce3d243e3cd967b2d9099709130eba3e474a..0000000000000000000000000000000000000000
--- a/debian/patches/0005-config-Clear-error-after-submission-URL-lookup-fails.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
-Date: Tue, 1 Oct 2019 13:42:11 +0000
-Subject: config: Clear error after submission URL lookup fails
-
-Otherwise we have a dangling pointer causing a crash when the error
-value is reused.
----
- src/gclue-config.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/gclue-config.c b/src/gclue-config.c
-index df4adcc..9ae2367 100644
---- a/src/gclue-config.c
-+++ b/src/gclue-config.c
-@@ -255,7 +255,7 @@ load_wifi_config (GClueConfig *config)
-                                                        &error);
-         if (error != NULL) {
-                 g_debug ("No wifi submission URL: %s", error->message);
--                g_error_free (error);
-+                g_clear_error (&error);
-                 priv->wifi_submit_url = g_strdup (DEFAULT_WIFI_SUBMIT_URL);
-         }
- 
diff --git a/debian/patches/02-move-demo-lib.patch b/debian/patches/02-move-demo-lib.patch
deleted file mode 100644
index a6521336f37a2a77804a0e4d57b79676f8ca3d8c..0000000000000000000000000000000000000000
--- a/debian/patches/02-move-demo-lib.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-Description: Move the demos from /usr/share to /usr/lib
-Author: Laurent Bigonville <bigon@debian.org>
-
---- a/demo/geoclue-where-am-i.desktop.in.in
-+++ b/demo/geoclue-where-am-i.desktop.in.in
-@@ -3,7 +3,7 @@ Name=Where am I?
- GenericName=Demo geolocation application
- Comment=Find your current location
- Keywords=geolocation;
--Exec=@libexecdir@/geoclue-2.0/demos/where-am-i
-+Exec=/usr/lib/geoclue-2.0/demos/where-am-i
- Icon=mark-location-symbolic
- NoDisplay=true
- Terminal=true
---- a/demo/geoclue-demo-agent.desktop.in.in
-+++ b/demo/geoclue-demo-agent.desktop.in.in
-@@ -2,7 +2,7 @@
- Name=Geoclue Demo agent
- GenericName=Demo geoclue agent
- Keywords=geolocation;
--Exec=@libexecdir@/geoclue-2.0/demos/agent
-+Exec=/usr/lib/geoclue-2.0/demos/agent
- Icon=mark-location-symbolic
- NotShowIn=GNOME;
- NoDisplay=true
diff --git a/debian/patches/fix-nowifi-query.patch b/debian/patches/fix-nowifi-query.patch
new file mode 100644
index 0000000000000000000000000000000000000000..15147a8c876208bfadcea07c073c026fbd0b6f78
--- /dev/null
+++ b/debian/patches/fix-nowifi-query.patch
@@ -0,0 +1,66 @@
+Description: Fix getting a location if the computer has no wifi card
+ This reverts 2 upstream commits: 194529c7e7123b06d41eb8025cd4375aba271068 and
+ 715cfbf5bec8002fb1e9759b6c34bc070f977807
+Origin: vendor
+Bug: https://gitlab.freedesktop.org/geoclue/geoclue/-/issues/142
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=978437
+
+--- a/src/gclue-wifi.c
++++ b/src/gclue-wifi.c
+@@ -837,7 +837,6 @@ gclue_wifi_get_accuracy_level (GClueWifi
+         return wifi->priv->accuracy_level;
+ }
+ 
+-/* Can return NULL without setting @error, signifying an empty BSS list. */
+ static GList *
+ get_bss_list (GClueWifi *wifi,
+               GError   **error)
+@@ -859,22 +858,8 @@ gclue_wifi_create_query (GClueWebSource
+ {
+         GList *bss_list; /* As in Access Points */
+         SoupMessage *msg;
+-        g_autoptr(GError) local_error = NULL;
+ 
+-        bss_list = get_bss_list (GCLUE_WIFI (source), &local_error);
+-        if (local_error != NULL) {
+-                g_propagate_error (error, g_steal_pointer (&local_error));
+-                return NULL;
+-        }
+-
+-        /* Empty list? */
+-        if (bss_list == NULL) {
+-                g_set_error_literal (error,
+-                                     G_IO_ERROR,
+-                                     G_IO_ERROR_FAILED,
+-                                     "No WiFi networks found");
+-                return NULL;
+-        }
++        bss_list = get_bss_list (GCLUE_WIFI (source), NULL);
+ 
+         msg = gclue_mozilla_create_query (bss_list, NULL, error);
+         g_list_free (bss_list);
+@@ -896,22 +881,10 @@ gclue_wifi_create_submit_query (GClueWeb
+ {
+         GList *bss_list; /* As in Access Points */
+         SoupMessage * msg;
+-        g_autoptr(GError) local_error = NULL;
+ 
+-        bss_list = get_bss_list (GCLUE_WIFI (source), &local_error);
+-        if (local_error != NULL) {
+-                g_propagate_error (error, g_steal_pointer (&local_error));
++        bss_list = get_bss_list (GCLUE_WIFI (source), error);
++        if (bss_list == NULL)
+                 return NULL;
+-        }
+-
+-        /* Empty list? */
+-        if (bss_list == NULL) {
+-                g_set_error_literal (error,
+-                                     G_IO_ERROR,
+-                                     G_IO_ERROR_FAILED,
+-                                     "No WiFi networks found");
+-                return NULL;
+-        }
+ 
+         msg = gclue_mozilla_create_submit_query (location,
+                                                  bss_list,
diff --git a/debian/patches/series b/debian/patches/series
index a63e7502c3c20f3c90c37132e06d503994697fb6..edb467d2529449c514e8e1c7f7d41c8cc5b0583c 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,5 +1,5 @@
-02-move-demo-lib.patch
-0001-service-Check-the-maximum-allowed-accuracy-level-eve.patch
 0002-config-Make-the-Mozilla-API-key-configurable.patch
 0003-service-Sync-in_use-property-when-apps-get-connected.patch
-0005-config-Clear-error-after-submission-URL-lookup-fails.patch
+0003-Revert-Fixed-hang-on-startup-when-client-app-is-a-sy.patch
+0004-service-Stop-the-client-for-system-applications-when.patch
+fix-nowifi-query.patch
diff --git a/debian/rules b/debian/rules
index 440da9159c13c93d4b3d6fe01ef13a2f9f553c31..154f95db76e59fb7441303855c31d7d658f7fdb0 100755
--- a/debian/rules
+++ b/debian/rules
@@ -26,7 +26,7 @@ ifeq ($(shell dpkg-vendor --query vendor),Debian)
 endif
 
 override_dh_auto_configure:
-	dh_auto_configure -- --libexecdir=/usr/lib/geoclue-2.0 \
+	dh_auto_configure -- --libexecdir=/usr/libexec \
                              -Ddbus-srv-user=geoclue \
                              -Dsystemd-system-unit-dir=/lib/systemd/system \
 			     ${BUILD_DOC} \
@@ -40,13 +40,11 @@ override_dh_auto_test:
 	# does not include.
 	dh_auto_test || true
 
-override_dh_auto_install:
-	dh_auto_install
-	mv $(CURDIR)/debian/tmp/usr/lib/geoclue-2.0/geoclue-2.0/demos \
-		$(CURDIR)/debian/tmp/usr/lib/geoclue-2.0/demos
-
 %:
-	dh $@ --with autoreconf,gir
+	dh $@ --with gir
 
 override_dh_missing:
 	dh_missing --list-missing
+
+override_dh_installchangelogs:
+	dh_installchangelogs NEWS
diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..33c3a640d2a84306b6a8b5640692ac3481739e65
--- /dev/null
+++ b/debian/salsa-ci.yml
@@ -0,0 +1,4 @@
+---
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
new file mode 100644
index 0000000000000000000000000000000000000000..0bb5860d208f524cc6eb2468b63ed8935a3cdae2
--- /dev/null
+++ b/debian/upstream/metadata
@@ -0,0 +1,2 @@
+Repository: https://gitlab.freedesktop.org/geoclue.git
+Repository-Browse: https://gitlab.freedesktop.org/geoclue
diff --git a/demo/meson.build b/demo/meson.build
index 99c094f3d6a7e18cbee247b0cc0a361ef098c41a..1427fbe840066a4f28a465cc2693fdf6c812d8c8 100644
--- a/demo/meson.build
+++ b/demo/meson.build
@@ -29,18 +29,16 @@ endif
 
 if get_option('demo-agent')
     include_dirs = [ configinc,
-                     libgeoclue_public_api_inc,
-                     libgeoclue_agent_inc ]
+                     libgeoclue_public_api_inc ]
 
     sources = [ 'gclue-service-agent.h',
                 'gclue-service-agent.c',
                 'agent.c',
-                libgeoclue_agent_sources[1] ]
+                 geoclue_agent_sources ]
     deps = base_deps + [ dependency('libnotify') ]
     executable('agent',
                sources,
                include_directories: include_dirs,
-               link_whole: [ libgeoclue_agent ],
                dependencies: deps,
                install: true,
                install_dir: demo_dir)
diff --git a/docs/geoclue-docs.xml b/docs/geoclue-docs.xml
index bb720e6b72770e2a0d90916b98c7323eef9fe743..c1c2268956feb6c0d7cfb8907a34244f85e49c9c 100644
--- a/docs/geoclue-docs.xml
+++ b/docs/geoclue-docs.xml
@@ -63,9 +63,9 @@
 	Geoclue service.
       </para>
     </partintro>
-    <xi:include href="../src/docs-org.freedesktop.GeoClue2.Manager.xml"/>
-    <xi:include href="../src/docs-org.freedesktop.GeoClue2.Client.xml"/>
-    <xi:include href="../src/docs-org.freedesktop.GeoClue2.Location.xml"/>
+    <xi:include href="../interface/docs-org.freedesktop.GeoClue2.Manager.xml"/>
+    <xi:include href="../interface/docs-org.freedesktop.GeoClue2.Client.xml"/>
+    <xi:include href="../interface/docs-org.freedesktop.GeoClue2.Location.xml"/>
     <xi:include href="xml/gclue-enums.xml"/>
   </reference>
 
@@ -77,7 +77,7 @@
 	agents must implement.
       </para>
     </partintro>
-    <xi:include href="../src/agent/docs-org.freedesktop.GeoClue2.Agent.xml"/>
+    <xi:include href="../interface/docs-org.freedesktop.GeoClue2.Agent.xml"/>
   </reference>
 
   <index>
diff --git a/docs/lib/libgeoclue-sections.txt b/docs/lib/libgeoclue-sections.txt
index 83add2c55e1736ff2bd0e6dfd22541871ace75a7..8352198e6bdece798a6320bfc6793c37c4e41103 100644
--- a/docs/lib/libgeoclue-sections.txt
+++ b/docs/lib/libgeoclue-sections.txt
@@ -58,6 +58,9 @@ gclue_client_complete_stop
 gclue_client_proxy_create
 gclue_client_proxy_create_finish
 gclue_client_proxy_create_sync
+gclue_client_proxy_create_full
+gclue_client_proxy_create_full_finish
+gclue_client_proxy_create_full_sync
 gclue_client_proxy_new
 gclue_client_proxy_new_finish
 gclue_client_proxy_new_sync
@@ -85,6 +88,9 @@ GClueClientProxyPrivate
 GClueAccuracyLevel
 GCLUE_TYPE_ACCURACY_LEVEL
 gclue_accuracy_level_get_type
+GClueClientProxyCreateFlags
+GCLUE_TYPE_CLIENT_PROXY_CREATE_FLAGS
+gclue_client_proxy_create_flags_get_type
 <SUBSECTION Private>
 gclue_accuracy_level_build_string_from_mask
 gclue_accuracy_level_get_string
diff --git a/docs/meson.build b/docs/meson.build
index ebd49eaacb64bc46819643f95e59279bf5e86e9e..8b440411107ec7de094d571b6a6caada78085481 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -1,27 +1,28 @@
-if get_option('libgeoclue')
-    subdir('lib')
-endif
+if get_option('enable-backend')
+  conf = configuration_data()
+  conf.set_quoted('VERSION', gclue_version)
+  version_file = configure_file(output: 'version.xml',
+                                input: 'version.xml.in',
+                                configuration: conf)
 
-conf = configuration_data()
-conf.set_quoted('VERSION', gclue_version)
-version_file = configure_file(output: 'version.xml',
-                              input: 'version.xml.in',
-                              configuration: conf)
+  content_files = [ '../COPYING',
+                    geoclue_iface_sources ]
+  scan_options = [ '--ignore-headers=config.h',
+                   '--rebuild-sections',
+                   '--rebuild-types' ]
+  # Extra options to supply to gtkdoc-mkdb
+  mkdb_options = [ '--output-format=xml' ]
 
-content_files = [ '../COPYING',
-                  dbus_gen_src,
-                  libgeoclue_agent_sources ]
-scan_options = [ '--ignore-headers=config.h',
-                 '--rebuild-sections',
-                 '--rebuild-types' ]
-# Extra options to supply to gtkdoc-mkdb
-mkdb_options = [ '--output-format=xml' ]
+  gnome.gtkdoc('geoclue',
+               main_xml: 'geoclue-docs.xml',
+               content_files: content_files,
+               scan_args: scan_options,
+               src_dir: libgeoclue_public_api_inc,
+               mkdb_args: mkdb_options,
+               dependencies: libgeoclue_dep,
+               install: true)
+endif
 
-gnome.gtkdoc('geoclue',
-             main_xml: 'geoclue-docs.xml',
-             content_files: content_files,
-             scan_args: scan_options,
-             src_dir: libgeoclue_public_api_inc,
-             mkdb_args: mkdb_options,
-             dependencies: libgeoclue_dep,
-             install: true)
+if get_option('libgeoclue')
+    subdir('lib')
+endif
diff --git a/src/create-unified-xml.py b/interface/create-unified-xml.py
similarity index 100%
rename from src/create-unified-xml.py
rename to interface/create-unified-xml.py
diff --git a/src/fi.w1.wpa_supplicant1.xml b/interface/fi.w1.wpa_supplicant1.xml
similarity index 100%
rename from src/fi.w1.wpa_supplicant1.xml
rename to interface/fi.w1.wpa_supplicant1.xml
diff --git a/interface/meson.build b/interface/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..9e230a7a6ab251aa0c0dbdf02197674b26efc2d4
--- /dev/null
+++ b/interface/meson.build
@@ -0,0 +1,95 @@
+dbus_interface_dir = join_paths(datadir, 'dbus-1', 'interfaces')
+
+geoclue_iface_sources = []
+
+# Client interface
+client_interface_xml = 'org.freedesktop.GeoClue2.Client.xml'
+geoclue_iface_sources += gnome.gdbus_codegen(
+    'gclue-client-interface',
+    client_interface_xml,
+    interface_prefix: 'org.freedesktop.GeoClue2.',
+    namespace: 'GClueDBus',
+    docbook: 'docs')
+# Location interface
+location_interface_xml = 'org.freedesktop.GeoClue2.Location.xml'
+geoclue_iface_sources += gnome.gdbus_codegen(
+    'gclue-location-interface',
+    location_interface_xml,
+    interface_prefix: 'org.freedesktop.GeoClue2.',
+    namespace: 'GClueDBus',
+    docbook: 'docs')
+# Manager interface
+manager_interface_xml = 'org.freedesktop.GeoClue2.Manager.xml'
+geoclue_iface_sources += gnome.gdbus_codegen(
+    'gclue-manager-interface',
+    manager_interface_xml,
+    interface_prefix: 'org.freedesktop.GeoClue2.',
+    namespace: 'GClueDBus',
+    docbook: 'docs')
+
+annotations = [[ 'fi.w1.wpa_supplicant1',
+                 'org.gtk.GDBus.C.Name',
+                 'WPA_Supplicant' ],
+               [ 'fi.w1.wpa_supplicant1.Interface',
+                 'org.gtk.GDBus.C.Name',
+                 'WPA_Interface' ],
+               [ 'fi.w1.wpa_supplicant1.BSS',
+                 'org.gtk.GDBus.C.Name',
+                 'WPA_BSS' ],
+               [ 'fi.w1.wpa_supplicant1.BSS:SSID',
+                 'org.gtk.GDBus.C.ForceGVariant',
+                 'whatever' ],
+               [ 'fi.w1.wpa_supplicant1.BSS:BSSID',
+                 'org.gtk.GDBus.C.ForceGVariant',
+                 'whatever' ],
+               [ 'fi.w1.wpa_supplicant1.Interface::BSSAdded',
+                 'org.gtk.GDBus.C.Name',
+                 'BSS_Added' ],
+               [ 'fi.w1.wpa_supplicant1.Interface::BSSRemoved',
+                 'org.gtk.GDBus.C.Name',
+                 'BSS_Removed' ]]
+
+geoclue_agent_sources = gnome.gdbus_codegen(
+    'geoclue-agent-interface',
+    'org.freedesktop.GeoClue2.Agent.xml',
+    interface_prefix: 'org.freedesktop.GeoClue2.',
+    namespace: 'GClue',
+    docbook: 'docs')
+geoclue_iface_sources += geoclue_agent_sources
+
+#libgeoclue_iface_inc = include_directories('.', '../..')
+
+if get_option('enable-backend')
+  wpa_supplicant_sources = gnome.gdbus_codegen(
+      'wpa_supplicant-interface',
+      'fi.w1.wpa_supplicant1.xml',
+      interface_prefix: 'fi.w1.wpa_supplicant1.',
+      annotations: annotations)
+
+  compass_iface_sources = gnome.gdbus_codegen(
+      'compass-interface',
+      'net.hadess.SensorProxy.xml',
+      interface_prefix: 'net.hadess.SensorProxy')
+endif
+
+install_data('org.freedesktop.GeoClue2.Agent.xml',
+             install_dir: dbus_interface_dir)
+
+interface_files = [ location_interface_xml,
+                    client_interface_xml,
+                    manager_interface_xml ]
+# Provide a single interface file too for backwards compatiblity.
+# At least gnome-settings-daemon currently relies on that.
+unified_interface_xml = 'org.freedesktop.GeoClue2.xml'
+python = find_program('python3')
+create_interface = find_program('create-unified-xml.py')
+cmd = [python, create_interface, '@OUTPUT@', '@INPUT@' ]
+
+custom_target('gclue-xml-interface',
+              input: interface_files,
+              output: unified_interface_xml,
+              install: true,
+              install_dir: dbus_interface_dir,
+              command: cmd)
+install_data(interface_files,
+             install_dir: dbus_interface_dir)
diff --git a/src/net.hadess.SensorProxy.xml b/interface/net.hadess.SensorProxy.xml
similarity index 100%
rename from src/net.hadess.SensorProxy.xml
rename to interface/net.hadess.SensorProxy.xml
diff --git a/src/agent/org.freedesktop.GeoClue2.Agent.xml b/interface/org.freedesktop.GeoClue2.Agent.xml
similarity index 100%
rename from src/agent/org.freedesktop.GeoClue2.Agent.xml
rename to interface/org.freedesktop.GeoClue2.Agent.xml
diff --git a/src/org.freedesktop.GeoClue2.Client.xml b/interface/org.freedesktop.GeoClue2.Client.xml
similarity index 98%
rename from src/org.freedesktop.GeoClue2.Client.xml
rename to interface/org.freedesktop.GeoClue2.Client.xml
index aae1d43001390938f1dbf5d09c9417b3e5e7abf1..ff9ba33f9d8f7df3b0bd24a9331c1cd2ba9149d4 100644
--- a/src/org.freedesktop.GeoClue2.Client.xml
+++ b/interface/org.freedesktop.GeoClue2.Client.xml
@@ -39,7 +39,7 @@
         Contains the current distance threshold in meters. This value is used
         by the service when it gets new location info. If the distance moved is
         below the threshold, it won't emit the LocationUpdated signal.
-        The default value is 0. When TimeThreshold is zero, it always emits
+        The default value is 0. When DistanceThreshold is zero, it always emits
         the signal.
     -->
     <property name="DistanceThreshold" type="u" access="readwrite">
diff --git a/src/org.freedesktop.GeoClue2.Location.xml b/interface/org.freedesktop.GeoClue2.Location.xml
similarity index 100%
rename from src/org.freedesktop.GeoClue2.Location.xml
rename to interface/org.freedesktop.GeoClue2.Location.xml
diff --git a/src/org.freedesktop.GeoClue2.Manager.xml b/interface/org.freedesktop.GeoClue2.Manager.xml
similarity index 100%
rename from src/org.freedesktop.GeoClue2.Manager.xml
rename to interface/org.freedesktop.GeoClue2.Manager.xml
diff --git a/libgeoclue/gclue-helpers.c b/libgeoclue/gclue-helpers.c
index 15ccc5bc5d31220a50447b0f66b8253e7dabd99f..bbb38097ced127b6f615493dc54b65eba6a4e6a5 100644
--- a/libgeoclue/gclue-helpers.c
+++ b/libgeoclue/gclue-helpers.c
@@ -35,20 +35,29 @@
  */
 
 typedef struct {
-        char              *desktop_id;
-        GClueAccuracyLevel accuracy_level;
+        char                        *desktop_id;
+        GClueAccuracyLevel           accuracy_level;
+        GClueClientProxyCreateFlags  flags;
 
+        GClueManager *manager;
         gulong notify_id;
 } ClientCreateData;
 
+typedef struct {
+        GClueManager  *manager;
+        char          *client_path;
+} ClientDestroyData;
+
 static ClientCreateData *
-client_create_data_new (const char        *desktop_id,
-                        GClueAccuracyLevel accuracy_level)
+client_create_data_new (const char                  *desktop_id,
+                        GClueAccuracyLevel           accuracy_level,
+                        GClueClientProxyCreateFlags  flags)
 {
         ClientCreateData *data = g_slice_new0 (ClientCreateData);
 
         data->desktop_id = g_strdup (desktop_id);
         data->accuracy_level = accuracy_level;
+        data->flags = flags;
 
         return data;
 }
@@ -56,10 +65,58 @@ client_create_data_new (const char        *desktop_id,
 static void
 client_create_data_free (ClientCreateData *data)
 {
+        g_clear_object (&data->manager);
         g_free (data->desktop_id);
         g_slice_free (ClientCreateData, data);
 }
 
+static ClientDestroyData *
+client_destroy_data_new (GClueManager *manager,
+                         const char   *client_path)
+{
+        ClientDestroyData *data = g_slice_new0 (ClientDestroyData);
+
+        if (manager)
+                data->manager = g_object_ref (manager);
+        data->client_path = g_strdup (client_path);
+
+        return data;
+}
+
+static void
+on_delete_client_finished (GObject      *source_object,
+                           GAsyncResult *res,
+                           gpointer      user_data)
+{
+        g_autoptr(GError) error = NULL;
+        ClientDestroyData *data = user_data;
+
+        if (!gclue_manager_call_delete_client_finish (
+                     GCLUE_MANAGER (source_object),
+                     res,
+                     &error)) {
+                g_warning ("GClue: Failed to automatically delete client: %s",
+                           error->message);
+        }
+
+        g_clear_object (&data->manager);
+        g_clear_pointer (&data->client_path, g_free);
+        g_slice_free (ClientDestroyData, data);
+}
+
+static void
+on_client_destroyed (gpointer data,
+                     GObject *where_the_object_was)
+{
+        ClientDestroyData *destroy_data = data;
+
+        gclue_manager_call_delete_client (destroy_data->manager,
+                                          destroy_data->client_path,
+                                          NULL,
+                                          on_delete_client_finished,
+                                          destroy_data);
+}
+
 static void
 on_client_proxy_ready (GObject      *source_object,
                        GAsyncResult *res,
@@ -67,6 +124,7 @@ on_client_proxy_ready (GObject      *source_object,
 {
         GTask *task = G_TASK (user_data);
         ClientCreateData *data;
+        ClientDestroyData *destroy;
         GClueClient *client;
         GError *error = NULL;
 
@@ -82,6 +140,16 @@ on_client_proxy_ready (GObject      *source_object,
         gclue_client_set_desktop_id (client, data->desktop_id);
         gclue_client_set_requested_accuracy_level (client, data->accuracy_level);
 
+        if (data->flags & GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE) {
+                destroy = client_destroy_data_new (
+                                  data->manager,
+                                  g_dbus_proxy_get_object_path (
+                                          G_DBUS_PROXY (client)));
+                g_object_weak_ref (G_OBJECT (client),
+                                   on_client_destroyed,
+                                   destroy);
+       }
+
         g_task_return_pointer (task, client, g_object_unref);
         g_object_unref (task);
 }
@@ -124,6 +192,7 @@ on_manager_proxy_ready (GObject      *source_object,
                         gpointer      user_data)
 {
         GTask *task = G_TASK (user_data);
+        ClientCreateData *data;
         GClueManager *manager;
         GError *error = NULL;
 
@@ -135,12 +204,30 @@ on_manager_proxy_ready (GObject      *source_object,
                 return;
         }
 
+        data = g_task_get_task_data (task);
+        data->manager = g_object_ref (manager);
         gclue_manager_call_get_client (manager,
                                        g_task_get_cancellable (task),
                                        on_get_client_ready,
                                        task);
 }
 
+static void
+on_client_proxy_full_finished (GObject      *source_object,
+                               GAsyncResult *res,
+                               gpointer      user_data)
+{
+        g_autoptr(GTask) task = user_data;
+        GClueClient *client;
+        GError *error = NULL;
+
+        client = gclue_client_proxy_create_finish (res, &error);
+        if (!client)
+                g_task_return_error (task, error);
+        else
+                g_task_return_pointer (task, client, g_object_unref);
+}
+
 /**
  * gclue_client_proxy_create:
  * @desktop_id: The desktop file id (the basename of the desktop file).
@@ -150,7 +237,11 @@ on_manager_proxy_ready (GObject      *source_object,
  * @user_data: User data to pass to @callback.
  *
  * A utility function to create a #GClueClientProxy without having to deal with
- * a #GClueManager.
+ * a #GClueManager. See also gclue_client_proxy_create_full() which improves
+ * resource management.
+ *
+ * This is identitcal to calling gclue_client_proxy_create_full() without any
+ * flags set.
  *
  * See #gclue_client_proxy_create_sync() for the synchronous, blocking version
  * of this function.
@@ -163,11 +254,102 @@ gclue_client_proxy_create (const char         *desktop_id,
                            gpointer            user_data)
 {
         GTask *task;
+
+        task = g_task_new (NULL, cancellable, callback, user_data);
+
+        gclue_client_proxy_create_full (desktop_id,
+                                        accuracy_level,
+                                        GCLUE_CLIENT_PROXY_CREATE_NONE,
+                                        cancellable,
+                                        on_client_proxy_full_finished,
+                                        task);
+}
+
+/**
+ * gclue_client_proxy_create_finish:
+ * @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to
+ *          gclue_client_proxy_create().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with gclue_client_proxy_create().
+ *
+ * Returns: (transfer full) (type GClueClientProxy): The constructed proxy
+ * object or %NULL if @error is set.
+ */
+GClueClient *
+gclue_client_proxy_create_finish (GAsyncResult *result,
+                                  GError      **error)
+{
+        g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
+
+        return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+/**
+ * gclue_client_proxy_create_sync:
+ * @desktop_id: The desktop file id (the basename of the desktop file).
+ * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * The synchronous and blocking version of #gclue_client_proxy_create().
+ * See also gclue_client_proxy_create_full_sync() which improves resource
+ * management.
+ *
+ * This function is identical to calling gclue_client_proxy_create_full_sync()
+ * without any flags set.
+ *
+ * Returns: (transfer full) (type GClueClientProxy): The constructed proxy
+ * object or %NULL if @error is set.
+ */
+GClueClient *
+gclue_client_proxy_create_sync (const char        *desktop_id,
+                                GClueAccuracyLevel accuracy_level,
+                                GCancellable      *cancellable,
+                                GError           **error)
+{
+        return gclue_client_proxy_create_full_sync (
+                       desktop_id,
+                       accuracy_level,
+                       GCLUE_CLIENT_PROXY_CREATE_NONE,
+                       cancellable,
+                       error);
+}
+
+/**
+ * gclue_client_proxy_create_full:
+ * @desktop_id: The desktop file id (the basename of the desktop file).
+ * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel.
+ * @flags: #GClueClientProxyCreateFlags to modify the creation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the results are ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * A utility function to create a #GClueClientProxy without having to deal with
+ * a #GClueManager.
+ *
+ * By setting the #GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE flag you can ensure
+ * that the client will be deleted again from the geoclue service when
+ * it is destroyed. This flag should be used unless you are doing explicit
+ * resource management.
+ *
+ * See #gclue_client_proxy_create_full_sync() for the synchronous, blocking
+ * version of this function.
+ */
+void
+gclue_client_proxy_create_full (const char                  *desktop_id,
+                                GClueAccuracyLevel           accuracy_level,
+                                GClueClientProxyCreateFlags  flags,
+                                GCancellable                *cancellable,
+                                GAsyncReadyCallback          callback,
+                                gpointer                     user_data)
+{
+        GTask *task;
         ClientCreateData *data;
 
         task = g_task_new (NULL, cancellable, callback, user_data);
 
-        data = client_create_data_new (desktop_id, accuracy_level);
+        data = client_create_data_new (desktop_id, accuracy_level, flags);
         g_task_set_task_data (task,
                               data,
                               (GDestroyNotify) client_create_data_free);
@@ -182,19 +364,19 @@ gclue_client_proxy_create (const char         *desktop_id,
 }
 
 /**
- * gclue_client_proxy_create_finish:
+ * gclue_client_proxy_create_full_finish:
  * @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to
  *          gclue_client_proxy_create().
  * @error: Return location for error or %NULL.
  *
- * Finishes an operation started with gclue_client_proxy_create().
+ * Finishes an operation started with gclue_client_proxy_create_full().
  *
  * Returns: (transfer full) (type GClueClientProxy): The constructed proxy
  * object or %NULL if @error is set.
  */
 GClueClient *
-gclue_client_proxy_create_finish (GAsyncResult *result,
-                                  GError      **error)
+gclue_client_proxy_create_full_finish (GAsyncResult *result,
+                                       GError      **error)
 {
         g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
 
@@ -221,22 +403,29 @@ on_client_proxy_created (GObject      *source_object,
 }
 
 /**
- * gclue_client_proxy_create_sync:
+ * gclue_client_proxy_create_full_sync:
  * @desktop_id: The desktop file id (the basename of the desktop file).
  * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel.
+ * @flags: #GClueClientProxyCreateFlags to modify the creation.
  * @cancellable: (allow-none): A #GCancellable or %NULL.
  * @error: Return location for error or %NULL.
  *
- * The synchronous and blocking version of #gclue_client_proxy_create().
+ * The synchronous and blocking version of #gclue_client_proxy_create_full().
+ *
+ * By setting the #GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE flag you can ensure
+ * that the client will be deleted again from the geoclue service when
+ * it is destroyed. This flag should be used unless you are doing explicit
+ * resource management.
  *
  * Returns: (transfer full) (type GClueClientProxy): The constructed proxy
  * object or %NULL if @error is set.
  */
 GClueClient *
-gclue_client_proxy_create_sync (const char        *desktop_id,
-                                GClueAccuracyLevel accuracy_level,
-                                GCancellable      *cancellable,
-                                GError           **error)
+gclue_client_proxy_create_full_sync (const char                 *desktop_id,
+                                     GClueAccuracyLevel          accuracy_level,
+                                     GClueClientProxyCreateFlags flags,
+                                     GCancellable               *cancellable,
+                                     GError                    **error)
 {
         GClueClient *client;
         ClientCreateSyncData *data = g_slice_new0 (ClientCreateSyncData);
diff --git a/libgeoclue/gclue-helpers.h b/libgeoclue/gclue-helpers.h
index 37997b0d56b0f5bf0eaa7c1226d3624bf13ad673..f43b4475bfae47def8de09094f4548d29f83de40 100644
--- a/libgeoclue/gclue-helpers.h
+++ b/libgeoclue/gclue-helpers.h
@@ -42,6 +42,20 @@ GClueClient *   gclue_client_proxy_create_sync   (const char         *desktop_id
                                                   GCancellable       *cancellable,
                                                   GError            **error);
 
+void            gclue_client_proxy_create_full        (const char                   *desktop_id,
+                                                       GClueAccuracyLevel            accuracy_level,
+                                                       GClueClientProxyCreateFlags   flags,
+                                                       GCancellable                 *cancellable,
+                                                       GAsyncReadyCallback           callback,
+                                                       gpointer                      user_data);
+GClueClient *   gclue_client_proxy_create_full_finish (GAsyncResult                 *result,
+                                                       GError                      **error);
+GClueClient *   gclue_client_proxy_create_full_sync   (const char                   *desktop_id,
+                                                       GClueAccuracyLevel            accuracy_level,
+                                                       GClueClientProxyCreateFlags  flags,
+                                                       GCancellable                 *cancellable,
+                                                       GError                      **error);
+
 G_END_DECLS
 
 #endif /* #ifndef __GCLUE_HELPERS_H__*/
diff --git a/libgeoclue/gclue-simple.c b/libgeoclue/gclue-simple.c
index 8facc7e1ee54656183fcc2e331bcc87899a14eee..33958e0ef84eebfab161170db2c4c5df7f2e9244 100644
--- a/libgeoclue/gclue-simple.c
+++ b/libgeoclue/gclue-simple.c
@@ -308,7 +308,7 @@ on_client_created (GObject      *source_object,
         GClueSimplePrivate *priv = simple->priv;
         GError *error = NULL;
 
-        priv->client = gclue_client_proxy_create_finish (res, &error);
+        priv->client = gclue_client_proxy_create_full_finish (res, &error);
         if (error != NULL) {
                 g_task_return_error (task, error);
                 g_clear_object (&priv->task);
@@ -341,11 +341,12 @@ gclue_simple_init_async (GAsyncInitable     *initable,
 
         task = g_task_new (initable, cancellable, callback, user_data);
 
-        gclue_client_proxy_create (simple->priv->desktop_id,
-                                   simple->priv->accuracy_level,
-                                   cancellable,
-                                   on_client_created,
-                                   task);
+        gclue_client_proxy_create_full (simple->priv->desktop_id,
+                                        simple->priv->accuracy_level,
+                                        GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE,
+                                        cancellable,
+                                        on_client_created,
+                                        task);
 }
 
 static gboolean
diff --git a/libgeoclue/meson.build b/libgeoclue/meson.build
index ef2761f9f789345d025df0641d3d03a1bc684429..e228ec34c6d8d4c1e5c9ccf7418c7aa79f76f234 100644
--- a/libgeoclue/meson.build
+++ b/libgeoclue/meson.build
@@ -1,29 +1,29 @@
-# FIXME: meson 0.46 doesn't seem to be actually installing the headers
-# generated by gnome.gdbus_codegen:
-#
-# https://github.com/mesonbuild/meson/pull/3487
-
 # Client interface
-gclue_client = gnome.gdbus_codegen('gclue-client',
-                               '../src/org.freedesktop.GeoClue2.Client.xml',
-                               interface_prefix: 'org.freedesktop.GeoClue2.',
-                               namespace: 'GClue',
-                               install_header: true,
-                               install_dir: include_subdir)
+gclue_client = gnome.gdbus_codegen(
+    'gclue-client',
+    '../interface/org.freedesktop.GeoClue2.Client.xml',
+    interface_prefix: 'org.freedesktop.GeoClue2.',
+    namespace: 'GClue',
+    install_header: true,
+    install_dir: include_subdir)
+
 # Location interface
-gclue_location = gnome.gdbus_codegen('gclue-location',
-                               '../src/org.freedesktop.GeoClue2.Location.xml',
-                               interface_prefix: 'org.freedesktop.GeoClue2.',
-                               namespace: 'GClue',
-                               install_header: true,
-                               install_dir: include_subdir)
+gclue_location = gnome.gdbus_codegen(
+    'gclue-location',
+    '../interface/org.freedesktop.GeoClue2.Location.xml',
+    interface_prefix: 'org.freedesktop.GeoClue2.',
+    namespace: 'GClue',
+    install_header: true,
+    install_dir: include_subdir)
+
 # Manager interface
-gclue_manager = gnome.gdbus_codegen('gclue-manager',
-                               '../src/org.freedesktop.GeoClue2.Manager.xml',
-                               interface_prefix: 'org.freedesktop.GeoClue2.',
-                               namespace: 'GClue',
-                               install_header: true,
-                               install_dir: include_subdir)
+gclue_manager = gnome.gdbus_codegen(
+    'gclue-manager',
+    '../interface/org.freedesktop.GeoClue2.Manager.xml',
+    interface_prefix: 'org.freedesktop.GeoClue2.',
+    namespace: 'GClue',
+    install_header: true,
+    install_dir: include_subdir)
 
 libgeoclue_sources = files('gclue-helpers.c', 'gclue-simple.c')
 libgeoclue_sources += gclue_client[0]
@@ -52,6 +52,11 @@ libgeoclue = library('geoclue-2',
                      version: '0.0.0',
                      install: true)
 
+libgeoclue_dep = declare_dependency(link_with: libgeoclue,
+                                    include_directories: include_dirs,
+                                    dependencies: base_deps,
+                                    sources: [ libgeoclue_sources, libgeoclue_headers ])
+
 gir = find_program('g-ir-scanner', required: false)
 vapigen = find_program('vapigen', required: false)
 enable_gir = get_option('introspection')
@@ -68,9 +73,8 @@ if gir.found() and enable_gir
                                identifier_prefix: 'GClue',
                                symbol_prefix: 'gclue',
                                export_packages: 'libgeoclue-' + gclue_api_version,
-                               dependencies: base_deps,
+                               dependencies: [libgeoclue_dep] + base_deps,
                                includes: [ 'GObject-2.0', 'Gio-2.0' ],
-                               include_directories: include_dirs,
                                install: true,
                                header: 'geoclue.h',
                                extra_args: [ '--quiet' ])
@@ -92,7 +96,3 @@ pkgconf.generate(version: gclue_version,
                  subdirs: [ header_dir ],
                  requires: pkg_requirements)
 
-libgeoclue_dep = declare_dependency(link_with: libgeoclue,
-                                    include_directories: include_dirs,
-                                    dependencies: base_deps,
-                                    sources: [ libgeoclue_sources, libgeoclue_headers ])
diff --git a/meson.build b/meson.build
index d738ef689122be069b6ab44ef6f90905437bc87e..f0ffe8be333c05e6451e0b66c1447e6e36c5f836 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,4 @@
-project('geoclue', 'c', version: '2.5.2', meson_version : '>= 0.47.2')
+project('geoclue', 'c', version: '2.5.7', meson_version : '>= 0.47.2')
 
 gclue_version = meson.project_version()
 ver_arr = gclue_version.split('.')
@@ -25,8 +25,8 @@ conf.set_quoted('PACKAGE_NAME', 'geoclue')
 conf.set_quoted('GETTEXT_PACKAGE', 'geoclue')
 conf.set_quoted('PACKAGE_TARNAME', 'geoclue')
 conf.set_quoted('PACKAGE_STRING', 'geoclue ' + gclue_version)
-conf.set_quoted('PACKAGE_URL', 'http://www.freedesktop.org/wiki/Software/GeoClue')
-conf.set_quoted('PACKAGE_BUGREPORT', 'http://bugs.freedesktop.org/enter_bug.cgi?product=GeoClue')
+conf.set_quoted('PACKAGE_URL', 'https://gitlab.freedesktop.org/geoclue/geoclue/wikis/home')
+conf.set_quoted('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/geoclue/geoclue/issues/new')
 conf.set_quoted('TEST_SRCDIR', meson.source_root() + '/data/')
 conf.set_quoted('LOCALEDIR', localedir)
 conf.set_quoted('SYSCONFDIR', sysconfdir)
@@ -50,6 +50,7 @@ if libm.found()
 endif
 
 subdir('public-api')
+subdir('interface')
 if get_option('enable-backend')
     subdir('src')
 endif
@@ -72,9 +73,11 @@ if get_option('gtk-doc') and get_option('libgeoclue')
   subdir('docs')
 endif
 
+systemd_unit_dir = 'N/A'
+
 # FIXME: Remove this once meson does it itself: https://github.com/mesonbuild/meson/issues/757
 summary = '''
-        GeoClue @0@
+        Geoclue @0@
         =================
 
         prefix:                   @1@
diff --git a/public-api/gclue-enums.h b/public-api/gclue-enums.h
index d1a988195b0e5123b4053dc079f0f8a7ac12ae17..33e499b08061e268efbea9a315d847178db31564 100644
--- a/public-api/gclue-enums.h
+++ b/public-api/gclue-enums.h
@@ -49,6 +49,18 @@ typedef enum {/*< underscore_name=gclue_accuracy_level>*/
 
 const char *gclue_accuracy_level_get_string (GClueAccuracyLevel val);
 
+/**
+ * GClueClientProxyCreateFlags:
+ * @GCLUE_CLIENT_PROXY_CREATE_NONE: Empty set of create flags
+ * @GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE:
+ *      Automatically delete the client from the server when the #GClueClient is
+ *      destroyed. This flag should usually be set.
+ **/
+typedef enum {/*< underscore_name=gclue_client_proxy_create_flags>*/
+        GCLUE_CLIENT_PROXY_CREATE_NONE        = 0,
+        GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE = 1 << 0,
+} GClueClientProxyCreateFlags;
+
 G_END_DECLS
 
 #endif /* GCLUE_ENUMS_H */
diff --git a/src/agent/meson.build b/src/agent/meson.build
deleted file mode 100644
index 781fefe13601952bf2f3559bf049062e8c6eeb55..0000000000000000000000000000000000000000
--- a/src/agent/meson.build
+++ /dev/null
@@ -1,16 +0,0 @@
-libgeoclue_agent_sources = gnome.gdbus_codegen(
-    'geoclue-agent-interface',
-    'org.freedesktop.GeoClue2.Agent.xml',
-    interface_prefix: 'org.freedesktop.GeoClue2.',
-    namespace: 'GClue',
-    docbook: 'docs')
-
-libgeoclue_agent_inc = include_directories('.', '../..')
-libgeoclue_agent = static_library('geoclue-agent',
-                                  libgeoclue_agent_sources,
-                                  dependencies: base_deps,
-                                  include_directories: libgeoclue_agent_inc,
-                                  install: false)
-
-install_data('org.freedesktop.GeoClue2.Agent.xml',
-             install_dir: dbus_interface_dir)
diff --git a/src/gclue-client-info.c b/src/gclue-client-info.c
index 4aab453a51c856163d142923f53bfacf664cdd79..d609b3449e1335a729b189cbf24116cb37c06d3b 100644
--- a/src/gclue-client-info.c
+++ b/src/gclue-client-info.c
@@ -74,6 +74,7 @@ gclue_client_info_finalize (GObject *object)
                 priv->watch_id = 0;
         }
 
+        g_clear_object (&priv->dbus_proxy);
         g_clear_pointer (&priv->bus_name, g_free);
         g_clear_pointer (&priv->xdg_id, g_free);
         g_clear_object (&priv->connection);
diff --git a/src/gclue-config.c b/src/gclue-config.c
index d259c713cf61fda4eb15861ce5492c87760b8d2e..0714d01b4baa7041b5a6ec9a7275ab1b03c9434b 100644
--- a/src/gclue-config.c
+++ b/src/gclue-config.c
@@ -232,7 +232,8 @@ load_wifi_config (GClueConfig *config)
                                                 "url",
                                                 &error);
         if (error != NULL) {
-                g_warning ("%s", error->message);
+                g_debug ("Failed to get config \"wifi/url\": %s",
+                         error->message);
                 g_clear_error (&error);
                 priv->wifi_url = g_strdup (DEFAULT_WIFI_URL);
         }
@@ -242,7 +243,7 @@ load_wifi_config (GClueConfig *config)
                                                     "submit-data",
                                                     &error);
         if (error != NULL) {
-                g_debug ("Failed to get config wifi/submit-data: %s",
+                g_debug ("Failed to get config \"wifi/submit-data\": %s",
                          error->message);
                 g_error_free (error);
 
@@ -254,8 +255,9 @@ load_wifi_config (GClueConfig *config)
                                                        "submission-url",
                                                        &error);
         if (error != NULL) {
-                g_debug ("No wifi submission URL: %s", error->message);
-                g_error_free (error);
+                g_debug ("Failed to get config \"wifi/submission-url\": %s",
+                         error->message);
+                g_clear_error (&error);
                 priv->wifi_submit_url = g_strdup (DEFAULT_WIFI_SUBMIT_URL);
         }
 
@@ -264,7 +266,8 @@ load_wifi_config (GClueConfig *config)
                                                         "submission-nick",
                                                         &error);
         if (error != NULL) {
-                g_debug ("No wifi submission nick: %s", error->message);
+                g_debug ("Failed to get config \"wifi/submission-nick\": %s",
+                         error->message);
                 g_error_free (error);
         }
 }
diff --git a/src/gclue-location-source.c b/src/gclue-location-source.c
index 79c78b72713e9cff720f60cb99816e02db887a0e..4ae4c57a862ce9c1cf5b0f3dbd1c4eb980e29fcf 100644
--- a/src/gclue-location-source.c
+++ b/src/gclue-location-source.c
@@ -192,6 +192,7 @@ gclue_location_source_finalize (GObject *object)
 
         gclue_location_source_stop (GCLUE_LOCATION_SOURCE (object));
         g_clear_object (&priv->location);
+        g_clear_object (&priv->time_threshold);
 
         G_OBJECT_CLASS (gclue_location_source_parent_class)->finalize (object);
 }
@@ -290,7 +291,7 @@ start_source (GClueLocationSource *source)
         if (source->priv->active_counter > 1) {
                 g_debug ("%s already active, not starting.",
                          G_OBJECT_TYPE_NAME (source));
-                return FALSE;
+                return TRUE;
         }
 
         if (source->priv->compute_movement) {
@@ -313,7 +314,7 @@ stop_source (GClueLocationSource *source)
         if (source->priv->active_counter == 0) {
                 g_debug ("%s already inactive, not stopping.",
                          G_OBJECT_TYPE_NAME (source));
-                return FALSE;
+                return TRUE;
         }
 
         source->priv->active_counter--;
diff --git a/src/gclue-locator.c b/src/gclue-locator.c
index a049fe5ca0483ec4292d81975793f2fcc45a77aa..650be4307eba4173d9dad8a3e870cdaca3f33306 100644
--- a/src/gclue-locator.c
+++ b/src/gclue-locator.c
@@ -301,8 +301,6 @@ gclue_locator_finalize (GObject *gsource)
         GList *node;
         GClueMinUINT *threshold;
 
-        G_OBJECT_CLASS (gclue_locator_parent_class)->finalize (gsource);
-
         threshold = gclue_location_source_get_time_threshold
                         (GCLUE_LOCATION_SOURCE (locator));
         g_signal_handlers_disconnect_by_func
@@ -325,7 +323,10 @@ gclue_locator_finalize (GObject *gsource)
         }
         g_list_free_full (priv->sources, g_object_unref);
         priv->sources = NULL;
+        g_list_free (priv->active_sources);
         priv->active_sources = NULL;
+
+        G_OBJECT_CLASS (gclue_locator_parent_class)->finalize (gsource);
 }
 
 static void
diff --git a/src/gclue-min-uint.c b/src/gclue-min-uint.c
index bc75e9a054d689229d063e882a91d7a67f65fe94..3d88f8900a6c430227e626d337f4b26c2bf95671 100644
--- a/src/gclue-min-uint.c
+++ b/src/gclue-min-uint.c
@@ -181,6 +181,8 @@ gclue_min_uint_get_value (GClueMinUINT *muint)
                 }
         }
 
+        g_list_free (values);
+
         return value;
 }
 
diff --git a/src/gclue-modem-manager.c b/src/gclue-modem-manager.c
index 66f883a8123a027d496412ebfcaf6a00da9988b4..411492f5dce492f2698f7122d13134a9ca16a7ca 100644
--- a/src/gclue-modem-manager.c
+++ b/src/gclue-modem-manager.c
@@ -523,7 +523,7 @@ clear_caps (GClueModemManager    *manager,
 
         return mm_modem_location_setup_sync (priv->modem_location,
                                              priv->caps,
-                                             FALSE,
+                                             TRUE,
                                              cancellable,
                                              error);
 }
diff --git a/src/gclue-mozilla.c b/src/gclue-mozilla.c
index 6d644a4fa049df3e2e038cd4e1631059e035942e..ffdb77c6f6d8ace62e71b0aefd5148ffcd1f967b 100644
--- a/src/gclue-mozilla.c
+++ b/src/gclue-mozilla.c
@@ -40,58 +40,66 @@
  * its easy to switch to Google's API.
  **/
 
-static char *
-variant_to_string (GVariant *variant, guint *len)
+#define BSSID_LEN 7
+#define BSSID_STR_LEN 18
+#define MAX_SSID_LEN 32
+
+static guint
+variant_to_string (GVariant *variant, guint max_len, char *ret)
 {
-        guint n_bytes, i;
-        char *ret;
+        guint i;
+        guint len;
 
-        n_bytes = g_variant_n_children (variant);
-        if (len != NULL)
-                *len = n_bytes;
-        if (n_bytes <= 0)
-                return NULL;
-        ret = g_malloc (n_bytes + 1);
-        ret[n_bytes] = '\0';
+        len = g_variant_n_children (variant);
+        if (len == 0)
+                return 0;
+        g_return_val_if_fail(len < max_len, 0);
+        ret[len] = '\0';
 
-        for (i = 0; i < n_bytes; i++)
+        for (i = 0; i < len; i++)
                 g_variant_get_child (variant,
                                      i,
                                      "y",
                                      &ret[i]);
 
-        return ret;
+        return len;
 }
 
-static char *
-get_ssid_from_bss (WPABSS *bss)
+static guint
+get_ssid_from_bss (WPABSS *bss, char *ssid)
 {
         GVariant *variant = wpa_bss_get_ssid (bss);
+        if (variant == NULL)
+                return 0;
 
-        return variant_to_string (variant, NULL);
+        return variant_to_string (variant, MAX_SSID_LEN, ssid);
 }
 
-static char *
-get_bssid_from_bss (WPABSS *bss)
+static gboolean
+get_bssid_from_bss (WPABSS *bss, char *bssid)
 {
         GVariant *variant;
-        char *raw_bssid;
-        char *bssid;
-        guint raw_len, len, i, j;
+        char raw_bssid[BSSID_LEN] = { 0 };
+        guint raw_len, i;
 
         variant = wpa_bss_get_bssid (bss);
+        if (variant == NULL)
+                return FALSE;
+
+        raw_len = variant_to_string (variant, BSSID_LEN, raw_bssid);
+        g_return_val_if_fail (raw_len == BSSID_LEN - 1, FALSE);
 
-        raw_bssid = variant_to_string (variant, &raw_len);
-        len = raw_len * 2 + raw_len;
-        bssid = g_malloc (len);
-        for (i = 0, j = 0; i < len; i = i + 3, j++)
-                g_snprintf (bssid + i,
-                            4,
-                           "%02x:",
-                           (unsigned char) raw_bssid[j]);
-        bssid[len - 1] = '\0';
-
-        return bssid;
+        for (i = 0; i < BSSID_LEN - 1; i++) {
+                unsigned char c = (unsigned char) raw_bssid[i];
+
+                if (i == BSSID_LEN - 2) {
+                        g_snprintf (bssid + (i * 3), 3, "%02x", c);
+                } else {
+                        g_snprintf (bssid + (i * 3), 4, "%02x:", c);
+                }
+        }
+
+        return TRUE;
 }
 
 static const char *
@@ -116,13 +124,28 @@ gclue_mozilla_create_query (GList        *bss_list, /* As in Access Points */
         char *data;
         gsize data_len;
         const char *uri;
+        guint n_non_ignored_bsss;
+        GList *iter;
 
         builder = json_builder_new ();
         json_builder_begin_object (builder);
 
         /* We send pure geoip query using empty object if both bss_list and
          * tower are NULL.
+         *
+         * If the list of non-ignored BSSs is <2, don’t bother submitting the
+         * BSS list as MLS will only do a geoip lookup anyway.
+         * See https://ichnaea.readthedocs.io/en/latest/api/geolocate.html#field-definition
          */
+        n_non_ignored_bsss = 0;
+        for (iter = bss_list; iter != NULL; iter = iter->next) {
+                WPABSS *bss = WPA_BSS (iter->data);
+
+                if (gclue_mozilla_should_ignore_bss (bss))
+                        continue;
+
+                n_non_ignored_bsss++;
+        }
 
         if (tower != NULL) {
                 json_builder_set_member_name (builder, "radioType");
@@ -147,15 +170,13 @@ gclue_mozilla_create_query (GList        *bss_list, /* As in Access Points */
                 json_builder_end_array (builder);
         }
 
-        if (bss_list != NULL) {
-                GList *iter;
-
+        if (n_non_ignored_bsss >= 2) {
                 json_builder_set_member_name (builder, "wifiAccessPoints");
                 json_builder_begin_array (builder);
 
                 for (iter = bss_list; iter != NULL; iter = iter->next) {
                         WPABSS *bss = WPA_BSS (iter->data);
-                        char *mac;
+                        char mac[BSSID_STR_LEN] = { 0 };
                         gint16 strength_dbm;
 
                         if (gclue_mozilla_should_ignore_bss (bss))
@@ -163,9 +184,8 @@ gclue_mozilla_create_query (GList        *bss_list, /* As in Access Points */
 
                         json_builder_begin_object (builder);
                         json_builder_set_member_name (builder, "macAddress");
-                        mac = get_bssid_from_bss (bss);
+                        get_bssid_from_bss (bss, mac);
                         json_builder_add_string_value (builder, mac);
-                        g_free (mac);
 
                         json_builder_set_member_name (builder, "signalStrength");
                         strength_dbm = wpa_bss_get_signal (bss);
@@ -329,7 +349,7 @@ gclue_mozilla_create_submit_query (GClueLocation   *location,
 
                 for (iter = bss_list; iter != NULL; iter = iter->next) {
                         WPABSS *bss = WPA_BSS (iter->data);
-                        char *mac;
+                        char mac[BSSID_STR_LEN] = { 0 };
                         gint16 strength_dbm;
                         guint16 frequency;
 
@@ -338,9 +358,8 @@ gclue_mozilla_create_submit_query (GClueLocation   *location,
 
                         json_builder_begin_object (builder);
                         json_builder_set_member_name (builder, "key");
-                        mac = get_bssid_from_bss (bss);
+                        get_bssid_from_bss (bss, mac);
                         json_builder_add_string_value (builder, mac);
-                        g_free (mac);
 
                         json_builder_set_member_name (builder, "signal");
                         strength_dbm = wpa_bss_get_signal (bss);
@@ -409,18 +428,22 @@ out:
 gboolean
 gclue_mozilla_should_ignore_bss (WPABSS *bss)
 {
-        char *ssid, *bssid;
+        char ssid[MAX_SSID_LEN] = { 0 };
+        char bssid[BSSID_STR_LEN] = { 0 };
+        guint len;
+
+        if (!get_bssid_from_bss (bss, bssid)) {
+                g_debug ("Ignoring WiFi AP with unknown BSSID..");
+                return TRUE;
+        }
 
-        ssid = get_ssid_from_bss (bss);
-        bssid = get_bssid_from_bss (bss);
-        if (ssid == NULL || g_str_has_suffix (ssid, "_nomap")) {
+        len = get_ssid_from_bss (bss, ssid);
+        if (len == 0 || g_str_has_suffix (ssid, "_nomap")) {
                 g_debug ("SSID for WiFi AP '%s' missing or has '_nomap' suffix."
                          ", Ignoring..",
                          bssid);
                 return TRUE;
         }
-        g_free (ssid);
-        g_free (bssid);
 
         return FALSE;
 }
diff --git a/src/gclue-nmea-source.c b/src/gclue-nmea-source.c
index c3a211bdf8cc0dec895ce8150abc9af6a2b6e3dc..c57da6847b08215733bd82cd46393a9047334364 100644
--- a/src/gclue-nmea-source.c
+++ b/src/gclue-nmea-source.c
@@ -482,8 +482,13 @@ on_read_gga_sentence (GObject      *object,
         }
         g_debug ("Network source sent: \"%s\"", message);
 
-        if (!g_str_has_prefix (message, "$GPGGA")) {
-                /* FIXME: Handle other useful NMEA sentences too */
+        if (!g_str_has_prefix (message, "$GAGGA") &&  /* Galieo */
+            !g_str_has_prefix (message, "$GBGGA") &&  /* BeiDou */
+            !g_str_has_prefix (message, "$BDGGA") &&  /* BeiDou */
+            !g_str_has_prefix (message, "$GLGGA") &&  /* GLONASS */
+            !g_str_has_prefix (message, "$GNGGA") &&  /* GNSS (combined) */
+            !g_str_has_prefix (message, "$GPGGA") &&  /* GPS, SBAS, QZSS */
+            !g_str_has_prefix (message, "$QZGGA")) {  /* QZSS */
                 g_debug ("Ignoring non-GGA sentence from NMEA source");
 
                 goto READ_NEXT_LINE;
diff --git a/src/gclue-service-client.c b/src/gclue-service-client.c
index 247fdb6a644fb693d5aa930aa43d5c7de1e23e92..62ea932557c5f02a576939dd7d4f5610a299b3d3 100644
--- a/src/gclue-service-client.c
+++ b/src/gclue-service-client.c
@@ -447,6 +447,7 @@ handle_post_agent_check_auth (StartData *data)
         GClueConfig *config;
         GClueAppPerm app_perm;
         guint32 uid;
+        gboolean system_app;
 
         uid = gclue_client_info_get_user_id (priv->client_info);
         max_accuracy = gclue_agent_get_max_accuracy_level (priv->agent_proxy);
@@ -471,8 +472,11 @@ handle_post_agent_check_auth (StartData *data)
         app_perm = gclue_config_get_app_perm (config,
                                               data->desktop_id,
                                               priv->client_info);
+        system_app = (gclue_client_info_get_xdg_id (priv->client_info) == NULL);
 
-        if (app_perm == GCLUE_APP_PERM_ALLOWED) {
+        if (app_perm == GCLUE_APP_PERM_ALLOWED || system_app) {
+                /* Since we have no reliable way to identify system apps, no
+                 * need for auth for them. */
                 complete_start (data);
                 return;
         }
@@ -556,7 +560,6 @@ gclue_service_client_handle_start (GClueDBusClient       *client,
         const char *desktop_id;
         GClueAppPerm app_perm;
         guint32 uid;
-        gboolean system_app = FALSE;
 
         if (priv->locator != NULL) {
                 /* Already started */
@@ -569,7 +572,6 @@ gclue_service_client_handle_start (GClueDBusClient       *client,
         if (desktop_id == NULL) {
                 /* Non-xdg app */
                 desktop_id = gclue_dbus_client_get_desktop_id (client);
-                system_app = TRUE;
         }
 
         if (desktop_id == NULL) {
@@ -605,14 +607,6 @@ gclue_service_client_handle_start (GClueDBusClient       *client,
         data->accuracy_level = ensure_valid_accuracy_level
                 (data->accuracy_level, GCLUE_ACCURACY_LEVEL_EXACT);
 
-        if (system_app) {
-                /* Since we have no reliable way to identify system apps, no
-                 * need for auth for them. */
-                complete_start (data);
-
-                return TRUE;
-        }
-
         /* No agent == No authorization */
         if (priv->agent_proxy == NULL) {
                 /* Already a pending Start()? Denied! */
diff --git a/src/gclue-service-manager.c b/src/gclue-service-manager.c
index 1d66ec463df26f782abd41bb6c8c172a3a96246e..d7f5e55c4901249cdd423c06fadb4018c6411a3b 100644
--- a/src/gclue-service-manager.c
+++ b/src/gclue-service-manager.c
@@ -258,6 +258,7 @@ on_client_info_new_ready (GObject      *source_object,
         GError *error = NULL;
         guint32 user_id;
         gint64 now;
+        gboolean system_app;
 
         info = gclue_client_info_new_finish (res, &error);
         if (info == NULL) {
@@ -277,7 +278,10 @@ on_client_info_new_ready (GObject      *source_object,
         agent_proxy = g_hash_table_lookup (priv->agents,
                                            GINT_TO_POINTER (user_id));
         now = g_get_monotonic_time ();
+
+        system_app = (gclue_client_info_get_xdg_id (info) == NULL);
         if (agent_proxy == NULL &&
+            !system_app &&
             now < (priv->init_time + AGENT_WAIT_TIMEOUT_USEC)) {
                 /* Its possible that geoclue was just launched on GetClient
                  * call, in which case agents need some time to register
diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c
index 4dbfc7cb29478640555caa6ca1a29e8b0749b1df..b06737d1eed6677b4f2aecb4da429d6b24977184 100644
--- a/src/gclue-wifi.c
+++ b/src/gclue-wifi.c
@@ -29,11 +29,15 @@
 #include "gclue-mozilla.h"
 
 #define WIFI_SCAN_TIMEOUT_HIGH_ACCURACY 10
-/* Since this is only used for city-level accuracy, 5 minutes betweeen each
+/* Since this is only used for city-level accuracy, 5 minutes between each
  * scan is more than enough.
  */
 #define WIFI_SCAN_TIMEOUT_LOW_ACCURACY  300
 
+#define BSSID_LEN 7
+#define BSSID_STR_LEN 18
+#define MAX_SSID_LEN 32
+
 /**
  * SECTION:gclue-wifi
  * @short_description: WiFi-based geolocation
@@ -192,58 +196,60 @@ on_bss_added (WPAInterface *object,
               GVariant     *properties,
               gpointer      user_data);
 
-static char *
-variant_to_string (GVariant *variant, guint *len)
+static guint
+variant_to_string (GVariant *variant, guint max_len, char *ret)
 {
-        guint n_bytes, i;
-        char *ret;
+        guint i;
+        guint len;
 
-        n_bytes = g_variant_n_children (variant);
-        if (len != NULL)
-                *len = n_bytes;
-        if (n_bytes <= 0)
-                return NULL;
-        ret = g_malloc (n_bytes + 1);
-        ret[n_bytes] = '\0';
+        len = g_variant_n_children (variant);
+        if (len == 0)
+                return 0;
+        g_return_val_if_fail(len < max_len, 0);
+        ret[len] = '\0';
 
-        for (i = 0; i < n_bytes; i++)
+        for (i = 0; i < len; i++)
                 g_variant_get_child (variant,
                                      i,
                                      "y",
                                      &ret[i]);
 
-        return ret;
+        return len;
 }
 
-static char *
-get_ssid_from_bss (WPABSS *bss)
+static guint
+get_ssid_from_bss (WPABSS *bss, char *ssid)
 {
         GVariant *variant = wpa_bss_get_ssid (bss);
 
-        return variant_to_string (variant, NULL);
+        return variant_to_string (variant, MAX_SSID_LEN, ssid);
 }
 
-static char *
-get_bssid_from_bss (WPABSS *bss)
+static gboolean
+get_bssid_from_bss (WPABSS *bss, char *bssid)
 {
         GVariant *variant;
-        char *raw_bssid;
-        char *bssid;
-        guint raw_len, len, i, j;
+        char raw_bssid[BSSID_LEN] = { 0 };
+        guint raw_len, i;
 
         variant = wpa_bss_get_bssid (bss);
+        if (variant == NULL)
+                return FALSE;
+
+        raw_len = variant_to_string (variant, BSSID_LEN, raw_bssid);
+        g_return_val_if_fail (raw_len == BSSID_LEN - 1, FALSE);
 
-        raw_bssid = variant_to_string (variant, &raw_len);
-        len = raw_len * 2 + raw_len;
-        bssid = g_malloc (len);
-        for (i = 0, j = 0; i < len; i = i + 3, j++)
-                g_snprintf (bssid + i,
-                            4,
-                           "%02x:",
-                           (unsigned char) raw_bssid[j]);
-        bssid[len - 1] = '\0';
+        for (i = 0; i < BSSID_LEN - 1; i++) {
+                unsigned char c = (unsigned char) raw_bssid[i];
 
-        return bssid;
+                if (i == BSSID_LEN - 2) {
+                        g_snprintf (bssid + (i * 3), 3, "%02x", c);
+                } else {
+                        g_snprintf (bssid + (i * 3), 4, "%02x:", c);
+                }
+        }
+
+        return TRUE;
 }
 
 static void
@@ -256,12 +262,11 @@ add_bss_proxy (GClueWifi *wifi,
         if (g_hash_table_replace (wifi->priv->bss_proxies,
                                   g_strdup (path),
                                   bss)) {
-                char *ssid;
+                char ssid[MAX_SSID_LEN] = { 0 };
 
                 wifi->priv->bss_list_changed = TRUE;
-                ssid = get_ssid_from_bss (bss);
+                get_ssid_from_bss (bss, ssid);
                 g_debug ("WiFi AP '%s' added.", ssid);
-                g_free (ssid);
         }
 }
 
@@ -275,12 +280,13 @@ on_bss_signal_notify (GObject    *gobject,
         const char *path;
 
         if (wpa_bss_get_signal (bss) <= -90) {
-                char *bssid = get_bssid_from_bss (bss);
+                char bssid[BSSID_STR_LEN] = { 0 };
+
+                get_bssid_from_bss (bss, bssid);
                 g_debug ("WiFi AP '%s' still has very low strength (%u dBm)"
-                         ", ignoring again..",
+                         ", ignoring again…",
                          bssid,
                          wpa_bss_get_signal (bss));
-                g_free (bssid);
                 return;
         }
 
@@ -300,7 +306,7 @@ on_bss_proxy_ready (GObject      *source_object,
         GClueWifi *wifi = GCLUE_WIFI (user_data);
         WPABSS *bss;
         GError *error = NULL;
-        char *ssid;
+        char ssid[MAX_SSID_LEN] = { 0 };
 
         bss = wpa_bss_proxy_new_for_bus_finish (res, &error);
         if (bss == NULL) {
@@ -316,18 +322,18 @@ on_bss_proxy_ready (GObject      *source_object,
                 return;
         }
 
-        ssid = get_ssid_from_bss (bss);
+        get_ssid_from_bss (bss, ssid);
         g_debug ("WiFi AP '%s' added.", ssid);
-        g_free (ssid);
 
         if (wpa_bss_get_signal (bss) <= -90) {
                 const char *path;
-                char *bssid = get_bssid_from_bss (bss);
+                char bssid[BSSID_STR_LEN] = { 0 };
+
+                get_bssid_from_bss (bss, bssid);
                 g_debug ("WiFi AP '%s' has very low strength (%u dBm)"
-                         ", ignoring for now..",
+                         ", ignoring for now…",
                          bssid,
                          wpa_bss_get_signal (bss));
-                g_free (bssid);
                 g_signal_connect (G_OBJECT (bss),
                                   "notify::signal",
                                   G_CALLBACK (on_bss_signal_notify),
@@ -360,16 +366,15 @@ on_bss_added (WPAInterface *object,
 static gboolean
 remove_bss_from_hashtable (const gchar *path, GHashTable *hash_table)
 {
-        char *ssid;
+        char ssid[MAX_SSID_LEN] = { 0 };
         WPABSS *bss = NULL;
 
         bss = g_hash_table_lookup (hash_table, path);
         if (bss == NULL)
                 return FALSE;
 
-        ssid = get_ssid_from_bss (bss);
+        get_ssid_from_bss (bss, ssid);
         g_debug ("WiFi AP '%s' removed.", ssid);
-        g_free (ssid);
 
         g_hash_table_remove (hash_table, path);
 
@@ -388,6 +393,35 @@ on_bss_removed (WPAInterface *object,
         remove_bss_from_hashtable (path, priv->ignored_bss_proxies);
 }
 
+static void
+start_wifi_scan (GClueWifi *wifi)
+{
+        GClueWifiPrivate *priv = wifi->priv;
+        GVariantBuilder builder;
+        GVariant *args;
+
+        g_debug ("Starting WiFi scan…");
+
+        if (priv->scan_done_id == 0)
+                priv->scan_done_id = g_signal_connect
+                                        (priv->interface,
+                                         "scan-done",
+                                         G_CALLBACK (on_scan_done),
+                                         wifi);
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+        g_variant_builder_add (&builder,
+                               "{sv}",
+                               "Type", g_variant_new ("s", "passive"));
+        args = g_variant_builder_end (&builder);
+
+        wpa_interface_call_scan (WPA_INTERFACE (priv->interface),
+                                 args,
+                                 NULL,
+                                 on_scan_call_done,
+                                 wifi);
+}
+
 static void
 cancel_wifi_scan (GClueWifi *wifi)
 {
@@ -410,33 +444,14 @@ on_scan_timeout (gpointer user_data)
 {
         GClueWifi *wifi = GCLUE_WIFI (user_data);
         GClueWifiPrivate *priv = wifi->priv;
-        GVariantBuilder builder;
-        GVariant *args;
 
-        if (priv->interface == NULL)
-                return FALSE;
-
-        g_debug ("WiFi scan timeout. Restarting-scan..");
+        g_debug ("WiFi scan timeout.");
         priv->scan_timeout = 0;
 
-        if (priv->scan_done_id == 0)
-                priv->scan_done_id = g_signal_connect
-                                        (priv->interface,
-                                         "scan-done",
-                                         G_CALLBACK (on_scan_done),
-                                         wifi);
-
-        g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
-        g_variant_builder_add (&builder,
-                               "{sv}",
-                               "Type", g_variant_new ("s", "passive"));
-        args = g_variant_builder_end (&builder);
+        if (priv->interface == NULL)
+                return G_SOURCE_REMOVE;
 
-        wpa_interface_call_scan (WPA_INTERFACE (priv->interface),
-                                 args,
-                                 NULL,
-                                 on_scan_call_done,
-                                 wifi);
+        start_wifi_scan (wifi);
 
         return FALSE;
 }
@@ -462,10 +477,19 @@ on_scan_done (WPAInterface *object,
 
         if (priv->bss_list_changed) {
                 priv->bss_list_changed = FALSE;
-                g_debug ("Refreshing location..");
+                g_debug ("Refreshing location…");
                 gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi));
         }
 
+        /* If there was another scan already scheduled, cancel that and
+         * re-schedule. Regardless of our internal book-keeping, this can happen
+         * if wpa_supplicant emits the `ScanDone` signal due to a scan being
+         * initiated by another client. */
+        if (priv->scan_timeout != 0) {
+                g_source_remove (priv->scan_timeout);
+                priv->scan_timeout = 0;
+        }
+
         /* With high-enough accuracy requests, we need to scan more often since
          * user's location can change quickly. With low accuracy, we don't since
          * we wouldn't want to drain power unnecessarily.
@@ -517,7 +541,7 @@ connect_bss_signals (GClueWifi *wifi)
                 return;
         }
 
-        on_scan_timeout (wifi);
+        start_wifi_scan (wifi);
 
         priv->bss_list_changed = TRUE;
         priv->bss_added_id = g_signal_connect (priv->interface,
@@ -545,14 +569,18 @@ disconnect_bss_signals (GClueWifi *wifi)
 {
         GClueWifiPrivate *priv = wifi->priv;
 
-        if (priv->bss_added_id == 0 || priv->interface == NULL)
-                return;
-
         cancel_wifi_scan (wifi);
-        g_signal_handler_disconnect (priv->interface, priv->bss_added_id);
-        priv->bss_added_id = 0;
-        g_signal_handler_disconnect (priv->interface, priv->bss_removed_id);
-        priv->bss_removed_id = 0;
+
+        if (priv->bss_added_id != 0) {
+                g_signal_handler_disconnect (priv->interface,
+                                             priv->bss_added_id);
+                priv->bss_added_id = 0;
+        }
+        if (priv->bss_removed_id != 0) {
+                g_signal_handler_disconnect (priv->interface,
+                                             priv->bss_removed_id);
+                priv->bss_removed_id = 0;
+        }
 
         g_hash_table_remove_all (priv->bss_proxies);
         g_hash_table_remove_all (priv->ignored_bss_proxies);
@@ -809,6 +837,7 @@ gclue_wifi_get_accuracy_level (GClueWifi *wifi)
         return wifi->priv->accuracy_level;
 }
 
+/* Can return NULL without setting @error, signifying an empty BSS list. */
 static GList *
 get_bss_list (GClueWifi *wifi,
               GError   **error)
@@ -829,10 +858,27 @@ gclue_wifi_create_query (GClueWebSource *source,
                          GError        **error)
 {
         GList *bss_list; /* As in Access Points */
+        SoupMessage *msg;
+        g_autoptr(GError) local_error = NULL;
 
-        bss_list = get_bss_list (GCLUE_WIFI (source), NULL);
+        bss_list = get_bss_list (GCLUE_WIFI (source), &local_error);
+        if (local_error != NULL) {
+                g_propagate_error (error, g_steal_pointer (&local_error));
+                return NULL;
+        }
+
+        /* Empty list? */
+        if (bss_list == NULL) {
+                g_set_error_literal (error,
+                                     G_IO_ERROR,
+                                     G_IO_ERROR_FAILED,
+                                     "No WiFi networks found");
+                return NULL;
+        }
 
-        return gclue_mozilla_create_query (bss_list, NULL, error);
+        msg = gclue_mozilla_create_query (bss_list, NULL, error);
+        g_list_free (bss_list);
+        return msg;
 }
 
 static GClueLocation *
@@ -849,13 +895,28 @@ gclue_wifi_create_submit_query (GClueWebSource  *source,
                                 GError         **error)
 {
         GList *bss_list; /* As in Access Points */
+        SoupMessage * msg;
+        g_autoptr(GError) local_error = NULL;
 
-        bss_list = get_bss_list (GCLUE_WIFI (source), error);
-        if (bss_list == NULL)
+        bss_list = get_bss_list (GCLUE_WIFI (source), &local_error);
+        if (local_error != NULL) {
+                g_propagate_error (error, g_steal_pointer (&local_error));
                 return NULL;
+        }
+
+        /* Empty list? */
+        if (bss_list == NULL) {
+                g_set_error_literal (error,
+                                     G_IO_ERROR,
+                                     G_IO_ERROR_FAILED,
+                                     "No WiFi networks found");
+                return NULL;
+        }
 
-        return gclue_mozilla_create_submit_query (location,
-                                                  bss_list,
-                                                  NULL,
-                                                  error);
+        msg = gclue_mozilla_create_submit_query (location,
+                                                 bss_list,
+                                                 NULL,
+                                                 error);
+        g_list_free (bss_list);
+        return msg;
 }
diff --git a/src/meson.build b/src/meson.build
index c0955de84da901e93f589e799bb184940a559cfd..e82245f1c3a3cc4b10e348020e2f11bbbc9ec9d9 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,74 +1,16 @@
-dbus_interface_dir = join_paths(datadir, 'dbus-1', 'interfaces')
-
-subdir('agent')
-
 geoclue_deps = base_deps + [ dependency('json-glib-1.0', version: '>= 0.14.0'),
                              dependency('libsoup-2.4', version: '>= 2.42.0') ]
 
-dbus_gen_src = []
-
-# Client interface
-client_interface_xml = 'org.freedesktop.GeoClue2.Client.xml'
-dbus_gen_src += gnome.gdbus_codegen(
-    'gclue-client-interface',
-    client_interface_xml,
-    interface_prefix: 'org.freedesktop.GeoClue2.',
-    namespace: 'GClueDBus',
-    docbook: 'docs')
-# Location interface
-location_interface_xml = 'org.freedesktop.GeoClue2.Location.xml'
-dbus_gen_src += gnome.gdbus_codegen(
-    'gclue-location-interface',
-    location_interface_xml,
-    interface_prefix: 'org.freedesktop.GeoClue2.',
-    namespace: 'GClueDBus',
-    docbook: 'docs')
-# Manager interface
-manager_interface_xml = 'org.freedesktop.GeoClue2.Manager.xml'
-dbus_gen_src += gnome.gdbus_codegen(
-    'gclue-manager-interface',
-    manager_interface_xml,
-    interface_prefix: 'org.freedesktop.GeoClue2.',
-    namespace: 'GClueDBus',
-    docbook: 'docs')
-sources = [ dbus_gen_src, libgeoclue_public_api_gen_sources[1] ]
-
-annotations = [[ 'fi.w1.wpa_supplicant1',
-                 'org.gtk.GDBus.C.Name',
-                 'WPA_Supplicant' ],
-               [ 'fi.w1.wpa_supplicant1.Interface',
-                 'org.gtk.GDBus.C.Name',
-                 'WPA_Interface' ],
-               [ 'fi.w1.wpa_supplicant1.BSS',
-                 'org.gtk.GDBus.C.Name',
-                 'WPA_BSS' ],
-               [ 'fi.w1.wpa_supplicant1.BSS:SSID',
-                 'org.gtk.GDBus.C.ForceGVariant',
-                 'whatever' ],
-               [ 'fi.w1.wpa_supplicant1.BSS:BSSID',
-                 'org.gtk.GDBus.C.ForceGVariant',
-                 'whatever' ],
-               [ 'fi.w1.wpa_supplicant1.Interface::BSSAdded',
-                 'org.gtk.GDBus.C.Name',
-                 'BSS_Added' ],
-               [ 'fi.w1.wpa_supplicant1.Interface::BSSRemoved',
-                 'org.gtk.GDBus.C.Name',
-                 'BSS_Removed' ]]
-sources += gnome.gdbus_codegen('wpa_supplicant-interface',
-                               'fi.w1.wpa_supplicant1.xml',
-                               interface_prefix: 'fi.w1.wpa_supplicant1.',
-                               annotations: annotations)
-
-sources += gnome.gdbus_codegen('compass-interface',
-                               'net.hadess.SensorProxy.xml',
-                               interface_prefix: 'net.hadess.SensorProxy')
+sources = [ libgeoclue_public_api_gen_sources[1],
+            geoclue_iface_sources,
+            wpa_supplicant_sources,
+            compass_iface_sources ]
 
 sources += gnome.genmarshal('gclue-marshal',
                             prefix: 'gclue_marshal',
                             sources: ['gclue-marshal.list'])
 
 include_dirs = [ configinc,
-                 libgeoclue_agent_inc,
                  libgeoclue_public_api_inc,
                  include_directories('..') ]
 
@@ -116,7 +58,7 @@ if get_option('nmea-source')
 endif
 
 c_args = [ '-DG_LOG_DOMAIN="Geoclue"' ]
-link_with = [ libgeoclue_public_api, libgeoclue_agent ]
+link_with = [ libgeoclue_public_api ]
 executable('geoclue',
            sources,
            link_with: link_with,
@@ -136,22 +78,3 @@ pkgconf.generate(version: gclue_version,
                  variables: [ 'apiversion=' + gclue_api_version,
                               'dbus_interface=' + dbus_interface,
                               'agent_dbus_interface=' + agent_dbus_interface ])
-
-interface_files = [ location_interface_xml,
-                    client_interface_xml,
-                    manager_interface_xml ]
-# Provide a single interface file too for backwards compatiblity.
-# At least gnome-settings-daemon currently relies on that.
-unified_interface_xml = 'org.freedesktop.GeoClue2.xml'
-python = find_program('python3')
-create_interface = find_program('create-unified-xml.py')
-cmd = [python, create_interface, '@OUTPUT@', '@INPUT@' ]
-
-custom_target('gclue-xml-interface',
-              input: interface_files,
-              output: unified_interface_xml,
-              install: true,
-              install_dir: dbus_interface_dir,
-              command: cmd)
-install_data(interface_files,
-             install_dir: dbus_interface_dir)