1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the Qt Mobility Components.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qgeopositioninfosource_maemo5_p.h"
43 #include "liblocationwrapper_p.h"
50 QGeoPositionInfoSourceMaemo::QGeoPositionInfoSourceMaemo(QObject *parent)
51 : QGeoPositionInfoSource(parent)
53 qDebug() << "* QGeoPositionInfoSourceMaemo Fremantle Backport";
55 timerInterval = DEFAULT_UPDATE_INTERVAL;
56 updateTimer = new QTimer(this);
57 updateTimer->setSingleShot(true);
58 connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateTimeoutElapsed()));
60 requestTimer = new QTimer(this);
61 requestTimer->setSingleShot(true);
62 connect(requestTimer, SIGNAL(timeout()), this, SLOT(requestTimeoutElapsed()));
64 connect(LiblocationWrapper::instance(), SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(newPositionUpdate(QGeoPositionInfo)));
66 errorOccurred = false;
69 positionInfoState = QGeoPositionInfoSourceMaemo::Undefined;
72 int QGeoPositionInfoSourceMaemo::init()
74 if (LiblocationWrapper::instance()->inited()) {
75 connect(LiblocationWrapper::instance(), SIGNAL(error()), this, SLOT(error()));
82 QGeoPositionInfo QGeoPositionInfoSourceMaemo::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
84 return (LiblocationWrapper::instance()->lastKnownPosition(fromSatellitePositioningMethodsOnly));
87 QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceMaemo::supportedPositioningMethods() const
89 QGeoPositionInfoSource::PositioningMethods methods;
91 if (!GConfItem("/system/nokia/location/gps-disabled").value().toBool())
92 methods |= SatellitePositioningMethods;
93 if (!GConfItem("/system/nokia/location/network-disabled").value().toBool())
94 methods |= NonSatellitePositioningMethods;
95 if (methods.testFlag(SatellitePositioningMethods) && methods.testFlag(NonSatellitePositioningMethods))
96 methods |= AllPositioningMethods;
101 void QGeoPositionInfoSourceMaemo::setUpdateInterval(int msec)
103 bool updateTimerInterval = false;
105 if (positionInfoState & QGeoPositionInfoSourceMaemo::PowersaveActive)
106 if (positionInfoState & QGeoPositionInfoSourceMaemo::Stopped)
107 updateTimerInterval = true;
110 timerInterval = MINIMUM_UPDATE_INTERVAL;
111 QGeoPositionInfoSource::setUpdateInterval(0);
113 timerInterval = (msec < MINIMUM_UPDATE_INTERVAL) ? MINIMUM_UPDATE_INTERVAL : msec;
114 QGeoPositionInfoSource::setUpdateInterval(timerInterval);
117 if (timerInterval >= POWERSAVE_THRESHOLD)
118 positionInfoState |= QGeoPositionInfoSourceMaemo::PowersaveActive;
120 positionInfoState &= ~QGeoPositionInfoSourceMaemo::PowersaveActive;
122 // If powersave has been active when new update interval has been set,
123 // ensure that timer is started.
124 if (updateTimerInterval)
125 startLocationDaemon();
127 // Ensure that new timer interval is taken into use immediately.
131 void QGeoPositionInfoSourceMaemo::setPreferredPositioningMethods(PositioningMethods methods)
133 QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
136 int QGeoPositionInfoSourceMaemo::minimumUpdateInterval() const
138 return MINIMUM_UPDATE_INTERVAL;
142 void QGeoPositionInfoSourceMaemo::startUpdates()
144 startLocationDaemon();
146 // Ensure that powersave is selected, if stopUpdates() has been called,
147 // but selected update interval is still greater than POWERSAVE_THRESHOLD.
148 if (timerInterval >= POWERSAVE_THRESHOLD)
149 positionInfoState |= QGeoPositionInfoSourceMaemo::PowersaveActive;
154 void QGeoPositionInfoSourceMaemo::stopUpdates()
156 positionInfoState &= ~QGeoPositionInfoSourceMaemo::PowersaveActive;
158 if (!(positionInfoState & QGeoPositionInfoSourceMaemo::RequestActive)) {
160 if (LiblocationWrapper::instance()->isActive())
161 LiblocationWrapper::instance()->stop();
164 errorOccurred = false;
167 positionInfoState &= ~QGeoPositionInfoSourceMaemo::Started;
168 positionInfoState |= QGeoPositionInfoSourceMaemo::Stopped;
171 void QGeoPositionInfoSourceMaemo::requestUpdate(int timeout)
173 int timeoutForRequest = 0;
176 if (LiblocationWrapper::instance()->isActive())
177 // If GPS is active, assume quick fix.
178 timeoutForRequest = DEFAULT_UPDATE_INTERVAL;
180 // Otherwise reserve longer time to get a fix.
181 timeoutForRequest = POWERSAVE_POWERON_PERIOD;
182 } else if (timeout < MINIMUM_UPDATE_INTERVAL) {
183 if (positionInfoState & QGeoPositionInfoSourceMaemo::RequestActive)
186 emit updateTimeout();
189 timeoutForRequest = timeout;
192 positionInfoState |= QGeoPositionInfoSourceMaemo::RequestActive;
194 if (!(LiblocationWrapper::instance()->isActive()))
195 LiblocationWrapper::instance()->start();
198 requestTimer->start(timeoutForRequest);
201 void QGeoPositionInfoSourceMaemo::newPositionUpdate(const QGeoPositionInfo &position)
204 Invalid fixes have NaN for horizontal accuracy regardless of
205 whether they come from satellite or non-satellite position methods.
207 Satellite fixes always have LOCATION_GPS_DEVICE_TIME_SET.
208 If this is not set and we have a numeric value for horizontal
209 accuracy then we are dealing with a non-satellite based positioning
212 Since QGeoPositionInfo instances are only considered valid if
213 they have a valid coordinate and a valid timestamp, we use
214 the current date and time as the timestamp for the network based
215 positioning. This will help in the case where someone wants to
216 reply a journey from a log file.
218 Based on some logging it looks like satellite and non-satellite
219 methods can be distinguished (after the initial fix) by whether
220 the time has been set and / or whether the horizontal accuracy
221 is above or below around 500 metres. Using the timestamp
222 appears to be more definitive than using the accuracy.
225 const bool horizontalAccuracyDefined = !qIsNaN(position.attribute(QGeoPositionInfo::HorizontalAccuracy));
226 const bool hasTimeStamp = !position.timestamp().isNull();
228 if (horizontalAccuracyDefined) {
230 //Valid satellite fix
231 lastUpdateFromSatellite = position;
233 //Valid non-satellite fix
234 QGeoPositionInfo networkPosition(position);
235 networkPosition.setTimestamp(QDateTime::currentDateTime());
236 lastUpdateFromNetwork = networkPosition;
239 //Invalid position update
241 lastUpdateFromSatellite = QGeoPositionInfo();
243 lastUpdateFromNetwork = QGeoPositionInfo();
248 void QGeoPositionInfoSourceMaemo::updateTimeoutElapsed()
250 QGeoPositionInfo position;
252 QGeoPositionInfoSource::PositioningMethods methods = preferredPositioningMethods();
254 if (methods.testFlag(AllPositioningMethods)) {
255 methods |= SatellitePositioningMethods;
256 methods |= NonSatellitePositioningMethods;
259 if (methods.testFlag(SatellitePositioningMethods) && !methods.testFlag(NonSatellitePositioningMethods)) {
260 //only SatellitePositioningMethods preferred
261 position = lastUpdateFromSatellite;
262 } else if (methods.testFlag(NonSatellitePositioningMethods) && !methods.testFlag(SatellitePositioningMethods)) {
263 //only NonSatellitePositioningMethods preferred
264 position = lastUpdateFromNetwork;
266 //AllPositioningMethods or none preferred
267 if (lastUpdateFromSatellite.isValid())
268 position = lastUpdateFromSatellite;
270 position = lastUpdateFromNetwork;
273 if (position.isValid()) {
274 errorOccurred = false;
277 if (positionInfoState & QGeoPositionInfoSourceMaemo::RequestActive) {
278 positionInfoState &= ~QGeoPositionInfoSourceMaemo::RequestActive;
279 requestTimer->stop();
281 if (positionInfoState & QGeoPositionInfoSourceMaemo::Stopped)
282 if (LiblocationWrapper::instance()->isActive())
283 LiblocationWrapper::instance()->stop();
285 // Ensure that requested position fix is emitted even though
286 // powersave is active and GPS would normally be off.
287 if ((positionInfoState & QGeoPositionInfoSourceMaemo::PowersaveActive) &&
288 (positionInfoState & QGeoPositionInfoSourceMaemo::Stopped)) {
289 emit positionUpdated(position);
293 // Make sure that if update is triggered when waking up, there
294 // is no false position update.
295 if (!((positionInfoState & QGeoPositionInfoSourceMaemo::PowersaveActive) &&
296 (positionInfoState & QGeoPositionInfoSourceMaemo::Stopped)))
297 emit positionUpdated(position);
299 // if an error occurs when we are updating periodically and we haven't
300 // sent an error since the last fix...
301 if (!(positionInfoState & QGeoPositionInfoSourceMaemo::RequestActive) &&
302 errorOccurred && !errorSent) {
304 // we need to emit the updateTimeout signal
305 emit updateTimeout();
311 void QGeoPositionInfoSourceMaemo::requestTimeoutElapsed()
314 emit updateTimeout();
316 positionInfoState &= ~QGeoPositionInfoSourceMaemo::RequestActive;
318 if (positionInfoState & QGeoPositionInfoSourceMaemo::Stopped)
319 if (LiblocationWrapper::instance()->isActive())
320 LiblocationWrapper::instance()->stop();
325 void QGeoPositionInfoSourceMaemo::error()
327 errorOccurred = true;
330 void QGeoPositionInfoSourceMaemo::activateTimer()
332 if (positionInfoState & QGeoPositionInfoSourceMaemo::RequestActive) {
333 updateTimer->start(MINIMUM_UPDATE_INTERVAL);
337 if (positionInfoState & QGeoPositionInfoSourceMaemo::PowersaveActive) {
338 if (positionInfoState & QGeoPositionInfoSourceMaemo::Started) {
339 // Cannot call stopUpdates() here since we want to keep powersave
341 if (LiblocationWrapper::instance()->isActive())
342 LiblocationWrapper::instance()->stop();
343 updateTimer->start(timerInterval - POWERSAVE_POWERON_PERIOD);
344 errorOccurred = false;
347 positionInfoState &= ~QGeoPositionInfoSourceMaemo::Started;
348 positionInfoState |= QGeoPositionInfoSourceMaemo::Stopped;
349 } else if (positionInfoState & QGeoPositionInfoSourceMaemo::Stopped) {
350 startLocationDaemon();
351 updateTimer->start(POWERSAVE_POWERON_PERIOD);
356 if (positionInfoState & QGeoPositionInfoSourceMaemo::Started)
357 updateTimer->start(timerInterval);
360 void QGeoPositionInfoSourceMaemo::startLocationDaemon()
362 if (!(LiblocationWrapper::instance()->isActive()))
363 LiblocationWrapper::instance()->start();
364 positionInfoState |= QGeoPositionInfoSourceMaemo::Started;
365 positionInfoState &= ~QGeoPositionInfoSourceMaemo::Stopped;
368 #include "moc_qgeopositioninfosource_maemo5_p.cpp"