@@ -11,7 +11,6 @@
*/
#include "hybrisprovider.h"
-#include "devicecontrol.h"
#include "geoclue_adaptor.h"
#include "position_adaptor.h"
@@ -39,6 +38,8 @@
#include <qofonoextmodemmanager.h>
+#include <android-config.h>
+
#include <strings.h>
#include <sys/time.h>
@@ -72,6 +73,9 @@
const QString LocationSettingsOldAgpsEnabledKey = QStringLiteral("location/agreement_accepted");
const QString LocationSettingsOldAgpsAgreementAcceptedKey = QStringLiteral("location/here_agreement_accepted");
+const int MaxXtraServers = 3;
+const QString XtraConfigFile = QStringLiteral("/etc/gps_xtra.ini");
+
void locationCallback(GpsLocation *location)
{
Location loc;
@@ -140,6 +144,53 @@
Q_ARG(QList<int>, usedPrns));
}
+#if GEOCLUE_ANDROID_GPS_INTERFACE == 3
+void gnssSvStatusCallback(GnssSvStatus *svStatus)
+{
+ QList<SatelliteInfo> satellites;
+ QList<int> usedPrns;
+
+ for (int i = 0; i < svStatus->num_svs; ++i) {
+ SatelliteInfo satInfo;
+ GnssSvInfo &svInfo = svStatus->gnss_sv_list[i];
+ satInfo.setPrn(svInfo.svid);
+ satInfo.setSnr(svInfo.c_n0_dbhz);
+ satInfo.setElevation(svInfo.elevation);
+ satInfo.setAzimuth(svInfo.azimuth);
+ satellites.append(satInfo);
+
+ if (svInfo.flags & GNSS_SV_FLAGS_USED_IN_FIX)
+ usedPrns.append(svInfo.svid);
+ }
+
+ QMetaObject::invokeMethod(staticProvider, "setSatellite", Qt::QueuedConnection,
+ Q_ARG(QList<SatelliteInfo>, satellites),
+ Q_ARG(QList<int>, usedPrns));
+}
+#endif
+
+#ifdef USE_GPS_VENDOR_EXTENSION
+void gnssSvStatusCallback_custom(GnssSvStatus *svStatus)
+{
+ QList<SatelliteInfo> satellites;
+ QList<int> usedPrns;
+
+ for (int i = 0; i < svStatus->num_svs; ++i) {
+ SatelliteInfo satInfo;
+ GnssSvInfo &svInfo = svStatus->sv_list[i];
+ satInfo.setPrn(svInfo.prn);
+ satInfo.setSnr(svInfo.snr);
+ satInfo.setElevation(svInfo.elevation);
+ satInfo.setAzimuth(svInfo.azimuth);
+ satellites.append(satInfo);
+ }
+
+ QMetaObject::invokeMethod(staticProvider, "setSatellite", Qt::QueuedConnection,
+ Q_ARG(QList<SatelliteInfo>, satellites),
+ Q_ARG(QList<int>, usedPrns));
+}
+#endif
+
bool nmeaChecksumValid(const QByteArray &nmea)
{
unsigned char checksum = 0;
@@ -230,6 +281,14 @@
QMetaObject::invokeMethod(staticProvider, "injectUtcTime", Qt::QueuedConnection);
}
+#if GEOCLUE_ANDROID_GPS_INTERFACE == 3
+void gnssSetSystemInfoCallback(const GnssSystemInfo *info)
+{
+ Q_UNUSED(info)
+ qCDebug(lcGeoclueHybris);
+}
+#endif
+
void agpsStatusCallback(AGpsStatus *status)
{
QHostAddress ipv4;
@@ -237,7 +296,7 @@
QByteArray ssid;
QByteArray password;
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 2
if (status->addr.ss_family == AF_INET) {
ipv4.setAddress(status->ipaddr);
} else if (status->addr.ss_family == AF_INET6) {
@@ -282,7 +341,7 @@
QMetaObject::invokeMethod(staticProvider, "xtraDownloadRequest", Qt::QueuedConnection);
}
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 2
ApnIpType fromContextProtocol(const QString &protocol)
{
if (protocol == QLatin1String("ip"))
@@ -316,12 +375,19 @@
locationCallback,
statusCallback,
svStatusCallback,
+#ifdef USE_GPS_VENDOR_EXTENSION
+ gnssSvStatusCallback_custom,
+#endif
nmeaCallback,
setCapabilitiesCallback,
acquireWakelockCallback,
releaseWakelockCallback,
createThreadCallback,
- requestUtcTimeCallback
+ requestUtcTimeCallback,
+#if GEOCLUE_ANDROID_GPS_INTERFACE == 3
+ gnssSetSystemInfoCallback,
+ gnssSvStatusCallback,
+#endif
};
AGpsCallbacks agpsCallbacks = {
@@ -429,12 +495,12 @@
HybrisProvider::HybrisProvider(QObject *parent)
: QObject(parent), m_gps(0), m_agps(0), m_agpsril(0), m_gpsni(0), m_xtra(0),
- m_status(StatusUnavailable), m_positionInjectionConnected(false), m_xtraDownloadReply(0),
- m_requestedConnect(false), m_gpsStarted(false), m_deviceControl(0),
+ m_status(StatusUnavailable), m_positionInjectionConnected(false), m_xtraDownloadReply(0), m_xtraServerIndex(0),
+ m_requestedConnect(false), m_gpsStarted(false), m_locationSettings(0),
m_networkManager(new NetworkManager(this)), m_cellularTechnology(0),
m_ofonoExtModemManager(new QOfonoExtModemManager(this)),
m_connectionManager(new QOfonoConnectionManager(this)), m_connectionContext(0), m_ntpSocket(0),
- m_agpsEnabled(false), m_agpsOnlineEnabled(false)
+ m_agpsEnabled(false), m_agpsOnlineEnabled(false), m_useForcedXtraInject(false), m_xtraUserAgent("")
{
if (staticProvider)
qFatal("Only a single instance of HybrisProvider is supported.");
@@ -447,14 +513,6 @@
staticProvider = this;
- m_locationSettings = new QFileSystemWatcher(this);
- connect(m_locationSettings, SIGNAL(fileChanged(QString)),
- this, SLOT(locationEnabledChanged()));
- connect(m_locationSettings, SIGNAL(directoryChanged(QString)),
- this, SLOT(locationEnabledChanged()));
- m_locationSettings->addPath(LocationSettingsDir);
- m_locationSettings->addPath(LocationSettingsFile);
-
new GeoclueAdaptor(this);
new PositionAdaptor(this);
new VelocityAdaptor(this);
@@ -463,6 +521,7 @@
m_manager = new QNetworkAccessManager(this);
connect(m_networkManager, SIGNAL(technologiesChanged()), this, SLOT(technologiesChanged()));
+ connect(m_networkManager, SIGNAL(stateChanged(QString)), this, SLOT(stateChanged(QString)));
technologiesChanged();
@@ -492,6 +551,48 @@
m_idleTimer.start(QuitIdleTime, this);
}
+ QString xtraUserAgentFileName;
+ QSettings settings(XtraConfigFile, QSettings::IniFormat);
+ QString xtraServer;
+
+ for (int i = 0; i < MaxXtraServers; i++) {
+ QString key = QString("xtra/XTRA_SERVER_%1").arg(i);
+ xtraServer = settings.value(key, "").toString();
+ if (xtraServer != "") {
+ m_xtraServers.enqueue(xtraServer);
+ }
+ }
+
+ m_useForcedXtraInject = settings.value("xtra/XTRA_FORCE_INJECT", "").toBool();
+
+ xtraUserAgentFileName = settings.value("xtra/XTRA_USERAGENT_FILE", "").toString();
+ if (xtraUserAgentFileName != "") {
+ QFile xtraUserAgentFile(xtraUserAgentFileName);
+ if (xtraUserAgentFile.open(QIODevice::ReadOnly)) {
+ m_xtraUserAgent = xtraUserAgentFile.readLine();
+ }
+ }
+
+ if (m_xtraServers.isEmpty()) {
+ QFile gpsConf(QStringLiteral("/system/etc/gps.conf"));
+ if (gpsConf.open(QIODevice::ReadOnly)) {
+
+ while (!gpsConf.atEnd()) {
+ const QByteArray line = gpsConf.readLine().trimmed();
+ if (line.startsWith('#'))
+ continue;
+
+ const QList<QByteArray> split = line.split('=');
+ if (split.length() != 2)
+ continue;
+
+ const QByteArray key = split.at(0).trimmed();
+ if (key == "XTRA_SERVER_1" || key == "XTRA_SERVER_2" || key == "XTRA_SERVER_3")
+ m_xtraServers.enqueue(QUrl::fromEncoded(split.at(1).trimmed()));
+ }
+ }
+ }
+
const hw_module_t *hwModule;
int error = hw_get_module(GPS_HARDWARE_MODULE_ID, &hwModule);
@@ -565,20 +666,23 @@
staticProvider = 0;
}
-void HybrisProvider::setDeviceController(DeviceControl *control)
+void HybrisProvider::setLocationSettings(LocationSettings *settings)
{
- if (m_deviceControl == control)
- return;
-
- if (m_deviceControl) {
- disconnect(m_deviceControl, SIGNAL(poweredChanged()),
- this, SLOT(locationEnabledChanged()));
+ if (!m_locationSettings) {
+ m_locationSettings = settings;
+ connect(m_locationSettings, &LocationSettings::locationEnabledChanged,
+ this, &HybrisProvider::locationEnabledChanged);
+ connect(m_locationSettings, &LocationSettings::gpsEnabledChanged,
+ this, &HybrisProvider::locationEnabledChanged);
+ connect(m_locationSettings, &LocationSettings::gpsFlightModeChanged,
+ this, &HybrisProvider::locationEnabledChanged);
+ connect(m_locationSettings, &LocationSettings::hereStateChanged,
+ this, &HybrisProvider::locationEnabledChanged);
+ connect(m_locationSettings, &LocationSettings::mlsEnabledChanged,
+ this, &HybrisProvider::locationEnabledChanged);
+ connect(m_locationSettings, &LocationSettings::mlsOnlineStateChanged,
+ this, &HybrisProvider::locationEnabledChanged);
}
-
- m_deviceControl = control;
-
- if (m_deviceControl)
- connect(m_deviceControl, SIGNAL(poweredChanged()), this, SLOT(locationEnabledChanged()));
}
void HybrisProvider::AddReference()
@@ -955,36 +1059,26 @@
qCDebug(lcGeoclueHybris) << "xtra download requested";
- QFile gpsConf(QStringLiteral("/system/etc/gps.conf"));
- if (!gpsConf.open(QIODevice::ReadOnly))
- return;
-
- while (!gpsConf.atEnd()) {
- const QByteArray line = gpsConf.readLine().trimmed();
- if (line.startsWith('#'))
- continue;
-
- const QList<QByteArray> split = line.split('=');
- if (split.length() != 2)
- continue;
-
- const QByteArray key = split.at(0).trimmed();
- if (key == "XTRA_SERVER_1" || key == "XTRA_SERVER_2" || key == "XTRA_SERVER_3")
- m_xtraServers.enqueue(QUrl::fromEncoded(split.at(1).trimmed()));
- }
+ m_xtraServerIndex = 0;
xtraDownloadRequestSendNext();
}
void HybrisProvider::xtraDownloadRequestSendNext()
{
- if (m_xtraServers.isEmpty())
+ if (m_xtraServerIndex >= m_xtraServers.count())
return;
qCDebug(lcGeoclueHybris) << m_xtraServers;
- m_xtraDownloadReply = m_manager->get(QNetworkRequest(m_xtraServers.dequeue()));
+ QNetworkRequest network_request(m_xtraServers[m_xtraServerIndex]);
+ if (m_xtraUserAgent != "") {
+ network_request.setRawHeader("User-Agent", m_xtraUserAgent.toUtf8());
+ }
+ m_xtraDownloadReply = m_manager->get(network_request);
connect(m_xtraDownloadReply, SIGNAL(finished()), this, SLOT(xtraDownloadFinished()));
+
+ m_xtraServerIndex++;
}
void HybrisProvider::xtraDownloadFinished()
@@ -1008,9 +1102,9 @@
QByteArray xtraData = m_xtraDownloadReply->readAll();
m_xtra->inject_xtra_data(xtraData.data(), xtraData.length());
- m_xtraDownloadReply = 0;
+ qCDebug(lcGeoclueHybris) << "injected " << xtraData.length() << " bytes of xtra data";
- m_xtraServers.clear();
+ m_xtraDownloadReply = 0;
}
}
@@ -1028,7 +1122,7 @@
qCDebug(lcGeoclueHybris) << "type:" << type << "status:" << status;
if (!m_agpsEnabled) {
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2 || GEOCLUE_ANDROID_GPS_INTERFACE == 1
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 1
m_agps->data_conn_failed();
#else
m_agps->data_conn_failed(AGPS_TYPE_SUPL);
@@ -1047,7 +1141,7 @@
break;
case GPS_RELEASE_AGPS_DATA_CONN:
// Immediately inform that connection is closed.
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2 || GEOCLUE_ANDROID_GPS_INTERFACE == 1
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 1
m_agps->data_conn_closed();
#else
m_agps->data_conn_closed(AGPS_TYPE_SUPL);
@@ -1096,7 +1190,7 @@
qCDebug(lcGeoclueHybris) << path << error;
if (path.contains(QStringLiteral("cellular")))
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2 || GEOCLUE_ANDROID_GPS_INTERFACE == 1
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 1
m_agps->data_conn_failed();
#else
m_agps->data_conn_failed(AGPS_TYPE_SUPL);
@@ -1108,7 +1202,7 @@
if (!selected) {
qCDebug(lcGeoclueHybris) << "User aborted mobile data connection";
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2 || GEOCLUE_ANDROID_GPS_INTERFACE == 1
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 1
m_agps->data_conn_failed();
#else
m_agps->data_conn_failed(AGPS_TYPE_SUPL);
@@ -1176,6 +1270,15 @@
}
}
+void HybrisProvider::stateChanged(const QString &state)
+{
+ if (state == "online") {
+ if (m_gpsStarted && m_useForcedXtraInject) {
+ gpsXtraDownloadRequest();
+ }
+ }
+}
+
void HybrisProvider::defaultDataModemChanged(const QString &modem)
{
qCDebug(lcGeoclueHybris) << "Default data modem changed to" << modem;
@@ -1209,7 +1312,7 @@
m_connectionContext->deleteLater();
m_connectionContext = 0;
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 2
if (m_agps->data_conn_open_with_apn_ip_type)
m_agps->data_conn_open_with_apn_ip_type(apn.constData(), fromContextProtocol(protocol));
else
@@ -1316,6 +1419,10 @@
}
m_gpsStarted = true;
+
+ if (m_useForcedXtraInject && m_networkManager->state() == "online") {
+ gpsXtraDownloadRequest();
+ }
}
void HybrisProvider::stopPositioningIfNeeded()
@@ -1361,37 +1468,20 @@
/*
Returns true if positioning is enabled, otherwise returns false.
-
- Currently checks the state of the Location enabled setting and flight mode.
*/
bool HybrisProvider::positioningEnabled()
{
- QSettings settings(LocationSettingsFile, QSettings::IniFormat);
-
- // check the keys related to agps enablement. We can have multiple agps providers.
- bool agpsAgreementAccepted = false;
- bool agpsEnabled = false;
- bool agpsOnlineEnabled = false;
- QString agpsProviders = settings.value(LocationSettingsAgpsProvidersKey, QStringLiteral("here")).toString();
- Q_FOREACH (const QString &agpsProvider, agpsProviders.split(',', QString::SkipEmptyParts)) {
- agpsAgreementAccepted = settings.value(LocationSettingsAgpsAgreementAcceptedKey.arg(agpsProvider), false).toBool();
- agpsEnabled = settings.value(LocationSettingsAgpsEnabledKey.arg(agpsProvider), false).toBool();
- agpsOnlineEnabled = settings.value(LocationSettingsAgpsOnlineEnabledKey.arg(agpsProvider), false).toBool();
- if (agpsAgreementAccepted && agpsEnabled && agpsOnlineEnabled) {
- break;
- }
- }
- // check the deprecated keys, also:
- bool oldAgpsAgreementAccepted = settings.value(LocationSettingsOldAgpsAgreementAcceptedKey, false).toBool();
- bool oldAgpsEnabled = settings.value(LocationSettingsOldAgpsEnabledKey, false).toBool();
- m_agpsEnabled = (agpsAgreementAccepted || oldAgpsAgreementAccepted) && (agpsEnabled || oldAgpsEnabled);
- m_agpsOnlineEnabled = agpsOnlineEnabled || (oldAgpsAgreementAccepted && oldAgpsEnabled);
-
- // check the keys related to the location and gps enablement, plus gps power state
- bool locationEnabled = settings.value(LocationSettingsEnabledKey, false).toBool();
- bool gpsEnabled = settings.value(LocationSettingsGpsEnabledKey, true).toBool(); // defaults to true if no key exists but location is enabled.
- bool powered = m_deviceControl->powered();
- return locationEnabled && gpsEnabled && powered;
+ // update our AGPS enablement states, used for position injection and mode capability.
+ m_agpsEnabled = (m_locationSettings->hereAvailable() && m_locationSettings->hereState() == LocationSettings::OnlineAGpsEnabled)
+ || (m_locationSettings->mlsAvailable() && m_locationSettings->mlsEnabled());
+ m_agpsOnlineEnabled = (m_locationSettings->hereAvailable() && m_locationSettings->hereState() == LocationSettings::OnlineAGpsEnabled)
+ || (m_locationSettings->mlsAvailable() && m_locationSettings->mlsOnlineState() == LocationSettings::OnlineAGpsEnabled);
+
+ // enable GPS positioning if location and the GPS are enabled, and the GPS is not in flight mode.
+ return m_locationSettings->locationEnabled()
+ && m_locationSettings->gpsAvailable()
+ && m_locationSettings->gpsEnabled()
+ && !m_locationSettings->gpsFlightMode();
}
quint32 HybrisProvider::minimumRequestedUpdateInterval() const
@@ -1424,7 +1514,7 @@
if (!m_agpsOnlineEnabled) {
qCDebug(lcGeoclueHybris) << "Online aGPS not enabled, not starting data connection.";
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2 || GEOCLUE_ANDROID_GPS_INTERFACE == 1
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 1
m_agps->data_conn_failed();
#else
m_agps->data_conn_failed(AGPS_TYPE_SUPL);
@@ -1516,7 +1606,7 @@
delete m_connectionContext;
m_connectionContext = 0;
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2 || GEOCLUE_ANDROID_GPS_INTERFACE == 1
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 1
m_agps->data_conn_failed();
#else
m_agps->data_conn_failed(AGPS_TYPE_SUPL);
|
@@ -15,7 +15,8 @@
#include <QtDBus/QDBusConnection>
#include "hybrisprovider.h"
-#include "devicecontrol.h"
+
+#include <locationsettings.h>
#include <unistd.h>
#include <sys/types.h>
@@ -54,7 +55,22 @@
supplementaryGroups[numberGroups++] = group->gr_gid;
-#if GEOCLUE_ANDROID_GPS_INTERFACE == 2
+ // remove audio, radio and bluetooth groups to avoid confusion in BSP
+ char *groups_to_remove[] = {"bluetooth", "radio", "audio", NULL};
+
+ int idx = 0;
+ while (groups_to_remove[idx]) {
+ group = getgrnam(groups_to_remove[idx]);
+ idx++;
+
+ if (idx + 1 < numberGroups) {
+ memmove((void*)&supplementaryGroups[idx], (void*)&supplementaryGroups[idx + 1], (numberGroups - idx - 1) * sizeof(gid_t));
+ }
+
+ numberGroups--;
+ }
+
+#if GEOCLUE_ANDROID_GPS_INTERFACE >= 2
group = getgrnam("net_raw");
if (group) {
if (numberGroups + 1 > NGROUPS_MAX)
@@ -68,15 +84,7 @@
if (numberGroups == -1)
qFatal("Failed to set supplementary groups, %s", strerror(errno));
- // Register service on DBus system bus prior to dropping privileges.
- QDBusConnection system = QDBusConnection::systemBus();
- DeviceControl control;
- if (!system.registerObject(QStringLiteral("/com/jollamobile/gps/Device"), &control))
- qFatal("Failed to register object /com/jollamobile/gps/Device");
- if (!system.registerService(QStringLiteral("com.jollamobile.gps")))
- qFatal("Failed to register service com.jollamobile.gps");
-
-#if GEOCLUE_ANDROID_GPS_INTERFACE != 2
+#if GEOCLUE_ANDROID_GPS_INTERFACE == 1
// Drop privileges.
result = setuid(realUid);
if (result == -1)
@@ -84,12 +92,13 @@
#endif
QDBusConnection session = QDBusConnection::sessionBus();
+ LocationSettings settings;
HybrisProvider provider;
+ provider.setLocationSettings(&settings);
if (!session.registerObject(QStringLiteral("/org/freedesktop/Geoclue/Providers/Hybris"), &provider))
qFatal("Failed to register object /org/freedesktop/Geoclue/Providers/Hybris");
if (!session.registerService(QStringLiteral("org.freedesktop.Geoclue.Providers.Hybris")))
qFatal("Failed to register service org.freedesktop.Geoclue.Providers.Hybris");
- provider.setDeviceController(&control);
return a.exec();
}
|